Java/문자열

[Java]StringBuilder 비교하는 방법

DevStory 2022. 8. 18.

StringBuilder 비교하는 방법

이번 포스팅은 두 개의 StringBuilder 객체를 비교하는 방법을 설명합니다.

 

먼저, 두 개의 StringBuilder 객체를 == 연산자, equals() 메서드를 사용하여 비교했을 때 어떠한 문제점이 발생하는지 알아봅시다.


문제점 1. == 연산자 사용 불가

다음 소스 코드의 실행 결과에서 확인할 수 있듯이 두 개의 StringBuilder객체를 == 연산자로 비교하면, false가 반환됩니다.

public static void main(String args[]) {
  StringBuilder sb1 = new StringBuilder("Hello");
  StringBuilder sb2 = new StringBuilder("Hello");

  System.out.println("sb1: " + sb1);
  System.out.println("sb2: " + sb2);
  System.out.println("sb1 == sb2: " + (sb1 == sb2));
}

[실행 결과]

sb1: Hello
sb2: Hello
sb1 == sb2: false

new 키워드를 사용하여 객체를 생성하면, 값이 아닌 힙 영역에 존재하는 객체의 주소 값을 비교하므로 false가 반환됩니다.

 

좀 더 이해하기 쉽게 다음 예시를 살펴봅시다.

 

다음 소스 코드는 Integer 타입의 변수에 정수 10을 할당합니다.

 

변수 intValue1, intValue2는 new 키워드를 사용하지 않았고 intValue3, intValue4는 new 키워드를 사용합니다.

public static void main(String args[]) {
  Integer intValue1 = 10;
  Integer intValue2 = 10;
  Integer intValue3 = new Integer(10);
  Integer intValue4 = new Integer(10);

  System.out.println("intValue1 == intValue2: " + (intValue1 == intValue2));
  System.out.println("intValue1 == intValue3: " + (intValue1 == intValue3));
  System.out.println("intValue3 == intValue4: " + (intValue3 == intValue4));
}

[실행 결과]

intValue1 == intValue2: true
intValue1 == intValue3: false
intValue3 == intValue4: false

intValue1 == intValue2

- 값을 비교합니다.

- 10과 10을 비교하므로 true가 반환됩니다.

 

intValue1 == intValue3

- intValue1의 값인 10과 intValue3이 참조하고 있는 객체의 주소 값을 비교합니다.

- intValue1의 값인 10과 intValue3이 참조하고 있는 주소 값을 비교하므로 false가 반환됩니다.

 

intValue3 == intValue4

- 객체의 주소 값을 비교합니다.

- intValue3이 참조하고 있는 주소와 intValue4 참조하고 있는 주소는 다르므로 false가 반환됩니다.


문제점 2. equals 메서드 사용 불가

String은 equals() 메서드로 비교할 수 있지만, StringBuilder는 equals() 메서드로 비교할 수 없습니다.

 

먼저, 두 개의 StringBuilder 객체를 equals() 메서드로 비교합니다.

public static void main(String args[]) {
  StringBuilder sb1 = new StringBuilder("Hello");
  StringBuilder sb2 = new StringBuilder("Hello");

  boolean isEquals = sb1.equals(sb2);

  System.out.println(sb1);
  System.out.println(sb2);
  System.out.println("sb1.equals(sb2): " + isEquals);
}

[실행 결과]

Hello
Hello
sb1.equals(sb2): false

StringBuilder 클래스의 equals() 메서드는 참조하고 있는 주소 값을 비교하므로 == 연산자와 반환 결과가 동일합니다.

 

하지만, Stirng 객체를 equals() 메서드로 비교하면 StringBuilder 클래스와 다르게 동작합니다.

public static void main(String args[]) {
  String strValue1 = new String("Hello");
  String strValue2 = new String("Hello");

  System.out.println("strValue1: " + strValue1);
  System.out.println("strValue2: " + strValue2);
  System.out.println("strValue1 == strValue2: " + (strValue1 == strValue2));
  System.out.println("strValue1.equals(strValue2): " + (strValue1.equals(strValue2)));
}

[실행 결과]

strValue1: Hello
strValue2: Hello
strValue1 == strValue2: false
strValue1.equals(strValue2): true

Java의 모든 클래스들은 최상위 클래스인 Object에서 파생됩니다. Object 클래스에는 equals() 메서드가 존재하며, 모든 클래스는 최상위 클래스인 Object에서 파생되므로 equals() 메서드를 재정의할 수 있습니다.

 

String 클래스는 값을 비교하도록 equals() 메서드가 재정의되었지만, StringBuilder 클래스는 equals() 메서드가 재정의되지 않았기에 여전히 참조하고 있는 주소 값을 비교합니다.


해결 방법

참조하고 있는 주소가 아닌 문자열 값을 비교하도록 StringBuilder 객체에서 toString() 메서드를 호출하여 문자열 값으로 변환 후 equals() 메서드를 사용합니다.

public static void main(String args[]) {
  StringBuilder sb1 = new StringBuilder("Hello");
  sb1.append(", Java");

  StringBuilder sb2 = new StringBuilder("Hello");
  sb2.append(", Java");

  boolean isToStringEqualse = sb1.toString().equals(sb2.toString());

  System.out.println(sb1);
  System.out.println(sb2);
  System.out.println("sb1.toString().equals(sb2.toString()): " + isToStringEqualse);
}

[실행 결과]

Hello, Java
Hello, Java
sb1.toString().equals(sb2.toString()): true
반응형

댓글