알고리즘 문제를 풀다가 반복문을 이용해 문자열을 합치는 부분이 있었다. 간단한 문제여서 String으로 문자열을 합쳤었는데 다른 사람들의 풀이를 보니 StringBuilder로 문제를 풀었다. 해당 문제를 String과 StringBuilder로 풀어봤는데 속도 차이가 많이 나서 어떤 차이 때문에 그런지 확인해보려고 한다.
String으로 풀었을 때StringBuilder로 풀었을 때
String
String은 불변(immutable)한 객체이며, 한 번 생성되면 내용을 변경할 수 없으며 길이가 정해져 있다. 이러한 특성 때문에 멀티스레드 환경에서 사용하기 적절하다.
단, JDK 1.5 이상부터는 위와 같이 + 로 문자열을 합칠 경우 컴파일러 단에서 자동으로 StringBuilder로 변경해준다고 한다.
String 객체는 Comparable 인터페이스를 상속하고 있기 때문에 equals 메서드로 문장이 동일한지 확인 가능하지만 StringBuilder는 Comparable 인터페이스를 상속하지 않기 때문에 equals 메서드가 없으며 비교 메서드가 따로 존재하지 않는다.
새로운 String 객체를 만들고 값을 할당할 때 JVM(Java Virtual Machine)은 내부적으로 가지고 있는 string pool에서 같은 값이 있는지 확인한다. 같은 값이 있을 경우, pool에서 해당 객체의 참조값을 반환하며 값이 없을 경우엔 pool에 값을 생성한 후 참조값을 반환한다. 그래서 각 다른 String 객체에 같은 값을 할당하면 가리키는 값이 동일하며 똑같은 값을 두 번 할당하지 않기 때문에 메모리 또한 절약할 수 있다.
String에서 언급했지만 StringBuilder는 Comparable 인터페이스를 상속하지 않기 때문에 equals 메서드를 이용한 비교가 불가능하다. 따라서 아래와 같이 String 형식으로 변환 후 비교를 진행해야 한다.
publicclassTEST{
publicstaticvoidmain(String[] args){
StringBuilder sb = new StringBuilder("ABC");
StringBuilder sb2 = new StringBuilder("ABC");
if (sb.toString().equals(sb2.toString())){
System.out.println("sb, sb2 is equal");
}
else{
System.out.println("sb, sb2 is not equal");
}
}
}
String과 다르게 StringBuilder는 객체에 동일한 값을 할당하더라도 참조값이 서로 다름을 확인할 수 있다.
결과에서 확실하게 알 수 있듯이 String을 + 문자로 계속 추가하게 되면 객체의 생성, 삭제가 계속해서 발생하게 되며 GC가 개입하기 때문에 단순히 문자열을 연결할 경우 속도면에서 매우 불리하다. 그리고 StringBuffer를 이용한 값이 StringBuilder보다 조금 더 오래 걸리는데, 그 이유가 StringBuffer는 내부적으로 thread-safe 를 유지하기 위해 별도의 작업을 진행하기 때문에 시간차이가 난다고 한다.
이메일 주소 검증 - 이메일 주소는 대부분 test@test.com 형태로, 아이디 부분은 영문 대/소문자, @는 하나이며 주소에는 .이 하나 이상이 들어간다고 가정했다. 이 정보를 기반으로 패턴을 정의하고 검증하는 과정을 거친다. 더 자세하게 검증 패턴을 만들기 위해서는 직접 구현하거나 검색을 통해 패턴을 알 수 있다.