[String 클래스] replace() , replaceAll(), replaceFirst()

그 전까지 String Class에 정의된 replace() 함수에 대해서 대단히 잘 못 오해를 하고 있었다. replaceFirst() 메서드와  같이 첫 번째로 일치하는 문자열이 있을 시 해당 문자열을 원하는 문자열로 변환하는 줄 알았다. 그런데 중요한 것은 지금 이 글을 쓰면서 replaceFirst()를 보니 매개변수로 정규식이 들어가네..? 진짜 String 클래스 볼 때 생각해야할 부분을 하나 제대로 알게 된 듯 하다. 그래서 한번 살펴봤다.

 

 

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html

 

String (Java SE 11 & JDK 11 )

Compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings. The character sequence represented by this String object is compared lexicographically to the character sequence represented by the argum

docs.oracle.com

replace(),replaceAll(),replaceFirst() 함수 정의

replace() 메서드에 대한 설명을 보면 [Returns a string resulting from replacing all occurrences of oldCharin this string with new Char] 기존에 문자에 대해서 모두 새로운 문자로 변환한다고 되어 있으며 2번째 메서드는 문자가 아닌 문자열 형태로 일치하는 문자열을 대체할 문자열로 변환해준다고 되어있다. 여기서 매개변수를 보면 CharSequence , char 로 문자, 문자열 그 자체이다. 이것이 무엇을 뜻하는지는 아래에서 한번 확인해볼 것이다. CharSequence로 되어 있는 부분을 확인해보니 String 클래스에서 구현한 인터페이스였다.

 

다음으로 replaceAll(String regex, String replacement),replaceFirst(String regex, String replacement)를 살펴보면 매개변수로 다음과 같이 정규표현식을 통해서 변환하고자 하는 문자열을 지정하고 원하는 문자열로 변환하는 형태의 메서드인 것을 볼 수 있다. 두 개의 차이점은 메서드명에서도 알 수 있듯이 처음으로 찾은 부분만 바꾸는지, 해당되는 부분은 모두 변경하는지 차이일 뿐 두 메서드 모두 정규식을 활용한다는 것이다. 실제 설명에서도 expression이라는 단어가 있는 것을 통해서도 짐작해볼 수 있었다.

 

그럼 이것들이 실제로 어떠한 영향을 주는지 확인해봤다.

String text = "동해물과 백두산이 마르고 닳도록 하나님이 보우하사 우리나라 만세";
        String s1_1 = text.replace('이', '가');
//        String s1_2 = text.replace('이 ', '가 '); 문자이기에 문자1개만 지정 가능
        String s2_1 = text.replace("이", "가");
        String s2_2 = text.replace("이 ", "가");
        String s3 = text.replaceAll("이", "가");
        String s4 = text.replaceFirst("이", "가");

        System.out.println("---------- replace() -----------");
        System.out.println("문자 = " + s1_1);
        System.out.println("문자열1 = " + s2_1);
        System.out.println("문자열2 = " + s2_2);
        System.out.println("---------- replaceAll() -----------");
        System.out.println("s3 = " + s3);
        System.out.println("---------- replaceFirst() -----------");
        System.out.println("s4 = " + s4);
        /*
			출력결과
            ---------- replace() -----------
            문자 = 동해물과 백두산가 마르고 닳도록 하나님가 보우하사 우리나라 만세
            문자열1 = 동해물과 백두산가 마르고 닳도록 하나님가 보우하사 우리나라 만세
            문자열2 = 동해물과 백두산가마르고 닳도록 하나님가보우하사 우리나라 만세
            ---------- replaceAll() -----------
            s3 = 동해물과 백두산가 마르고 닳도록 하나님가 보우하사 우리나라 만세
            ---------- replaceFirst() -----------
            s4 = 동해물과 백두산가 마르고 닳도록 하나님이 보우하사 우리나라 만세
        */

다음에서 볼 수 있는 것은 replace() 사용 시 문자, 문자열 모두 가능하다. 이때 고려할 부분은 문자 / 문자열 부분에서 지정할 때 혼동하지 않아야한다. 사실상 문자열로 지정을 해주는 경우가 대부분일 것이다. 이번 예제에서는 replaceAll(), replaceFirst() 에서도 replace()와 별반 다른점은 보이지 않는 듯 싶다. 물론 replaceFirst()는 당연히 처음 일치하는 부분만 변경할 것이다. 

 

그럼 다음 예제의 경우는 어떻게 되는지 살펴보자

String text = "동해물과 백두산이 마르고 닳도록 하나님이 보우하사 우리나라 만세.";
        String s1_1 = text.replace('.', '/');
        String s2_1 = text.replace(".", "/");
        String s2_2 = text.replace(". ", "/");
        String s3 = text.replaceAll(".", "/");
        String s4 = text.replaceFirst(".", "/");

        System.out.println("---------- replace() -----------");
        System.out.println("문자 = " + s1_1);
        System.out.println("문자열1 = " + s2_1);
        System.out.println("문자열2 = " + s2_2);
        System.out.println("---------- replaceAll() -----------");
        System.out.println("s3 = " + s3);
        System.out.println("---------- replaceFirst() -----------");
        System.out.println("s4 = " + s4);
        
        /*
			출력결과
           ---------- replace() -----------
            문자 = 동해물과 백두산이 마르고 닳도록 하나님이 보우하사 우리나라 만세/
            문자열1 = 동해물과 백두산이 마르고 닳도록 하나님이 보우하사 우리나라 만세/
            문자열2 = 동해물과 백두산이 마르고 닳도록 하나님이 보우하사 우리나라 만세.
            ---------- replaceAll() -----------
            s3 = ////////////////////////////////////
            ---------- replaceFirst() -----------
            s4 = /해물과 백두산이 마르고 닳도록 하나님이 보우하사 우리나라 만세.

        */

현재 원했던 기능은 "." -> "/"로 바꾸고 싶었다. 그래서 다음과 같이 replace(), replaceAll(), replaceFirst()를 통해서 각자 처리를해봤다. 이때 별 생각없이 모두 바꾸고 싶어서 replaceAll()을 사용했다고 가정해보자. 다음과 같이 모든 문자열이 다 변환되는 참사를 맛볼 수 있다. 그 이유는 JDK11 DOCS문서에서도 볼 수 있듯이 replace()를 제외한 두 메서드는 정규식을 활용하기 때문에 이와같이 생각하지 못했던 결과가 나타나게된다. 그러나 어떠한 조건을 제공하여 그에 맞는 문자열은 모두 변환시키거나 할 때 활용하면 좋은 효과를 볼 수 있을 것이다. 

 

결론은 메서드 하나를 쓰더라도 이러한 부분들을 한번 고려해보면서 사용하면 더욱 좋은 결과를 얻을 수 있다고 생각한다. 정규식도 문자열처리도 정말 중요하고 자주 사용하는 것이니만큼 이번에 학습한 내용이 이후  알고리즘을 풀거나할 때 제대로 알고 사용할  수 있는 좋은 경험이 될 것이다.

'TIL & WIL > TIL' 카테고리의 다른 글

프로그래머스 [120823] 성능 개선  (1) 2023.01.28
java.lang.ClassCastException  (1) 2023.01.26
형변환이 가능한 Overloading  (0) 2023.01.23
객체의 메서드 호출과 반환  (0) 2023.01.21
Githup 커밋 강제 되돌리기  (0) 2023.01.18