Effective Java : 아이템 63. 문자열 연결은 느리니 주의하라

    아이템 63. 문자열 연결은 느리니 주의하라

    • String은 불변 객체다.
      • 문자열 덧셈으로 String끼리 연결하면 각 문자열의 값을 복사한 후 붙여야 함. 
      • 따라서 문자열 n개를 잇는 시간은 n^2에 비례하게 됨.
    • 문자열 연결을 빠르게 하기 위해서는 Builder의 append(), toString()을 이용하면 됨. 

    문자열 n개를 잇는데 필요한 시간은 O(n^2)임. 

    • 문자열(String)은 불변 객체다. 따라서 문자열끼리 잇는 연산을 하려면, 각 문자열의 모든 내용을 복사한 다음에 새로운 객체를 만드는 작업을 해야한다. 이 연산의 시간복잡도는 O(n^2)이다.
    • 문자열 덧셈의 문제점을 해결하기 위해서는 StringBuilder의 append(), toString() 연산을 이용하면 된다.
    public class GoodStringConcat {
    
        // String은 불변 객체임. 두 문자열을 연결하기 위해서 양쪽 내용을 복사해서 붙여야 함.
        public static String slowStatement() {
            List<String> strings = List.of("A", "B", "C");
            String result = "";
            for (String string : strings) {
                result += string; // 문자열 연결
            }
            return result;
        }
    
        // Builder의 append() 메서드를 이용하면 빨라짐.
        public static String fastStatement() {
            List<String> strings = List.of("A", "B", "C");
            StringBuilder builder = new StringBuilder();
            for (String string : strings) {
                builder.append(string);
            }
            return builder.toString();
        }
    
        public static void main(String[] args) {
            System.out.println(slowStatement());
            System.out.println(fastStatement());
        }
    }

    문자열을 잇는데 시간은 얼마나 차이가 날까?

    아래 코드를 이용해서 UUID 10만개 문자열을 붙였을 때, 각각 걸리는 시간을 측정해봤다.  StringBuilder를 이용하는 것이 6000배 이상 빠르다. 

    • 문자열 덧셈 : 34824 ms
    • Builder 이용 : 5ms
    @Test
    void test1() {
    
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 100_000; i++) {
            list.add(UUID.randomUUID().toString());
        }
    
        String result = "";
        long s1 = System.currentTimeMillis();
        for (String s : list) {
            result += s;
        }
        long e1 = System.currentTimeMillis();
    
        StringBuilder builder = new StringBuilder();
        long s2 = System.currentTimeMillis();
        for (String s : list) {
            builder.append(s);
        }
        long e2 = System.currentTimeMillis();
    
        long t1 = e1 - s1;
        long t2 = e2 - s2;
        System.out.println("문자열 덧셈 걸린 시간 " + t1);
        System.out.println("Builder 걸린 시간 " + t2);
    }

    실행 결과는 다음과 같음.

    문자열 덧셈 걸린 시간 34824
    Builder 걸린 시간 5

    댓글

    Designed by JB FACTORY