Java/배열

[Java]두 배열을 비교하는 방법

DevStory 2022. 8. 17.

두 배열을 비교하는 방법

Java에서 두 배열을 비교해야 하는 경우 다음 조건을 만족하면 동일하다고 판단합니다.

- 두 배열은 모두 동일한 타입입니다.

- 두 배열은 동일한 수의 요소를 가지고 있으며, 정렬 순서도 동일해야 합니다.

- 주소 값이 아닌 기본 타입의 값을 비교합니다.

- 두 배열이 null로 할당되면 두 배열은 동일합니다.

 

이번 포스팅은 Arrays 클래스에서 제공하는 equals() 메서드와 deepEquals() 메서드를 사용하여 두 배열을 비교합니다.

 

Arrays 클래스의 compare() 메서드를 사용하여 두 배열을 비교할 수 있지만, compare() 메서드는 Java 1.9 버전 이상부터 사용할 수 있으므로 이번 포스팅에서 언급하지 않습니다.


== 연산자의 문제점

equals() 메서드와 deepEquals() 메서드 사용 방법을 설명하기 전에 두 개의 배열을 == 연산자로 비교했을 때, 어떤 문제가 발생하는지 알아봅시다.

 

다음 예제는 1부터 3까지 정수 값을 가지는 int 타입의 두 배열을 == 연산자로 비교합니다.

public static void main(String args[]) {
  int[] intArray1 = new int[] { 1, 2, 3 };
  int[] intArray2 = new int[] { 1, 2, 3 };

  if(intArray1 == intArray2) {
    System.out.println("두 배열은 동일합니다.");
  } else {
    System.out.println("두 배열은 동일하지 않습니다.");
  }
}

[실행 결과]

두 배열은 동일하지 않습니다.

int 타입의 배열 intArray1와 intArray2는 Heap 영역에 존재하는 배열의 값을 참조하고 있습니다.

 

따라서, 두 배열을 == 연산자로 비교하면 배열의 요소가 아닌 Heap 영역의 주소 값을 비교하므로 배열의 타입, 동일한 수의 요소 그리고 정렬 순서가 동일하더라도 두 배열은 동일하지 않습니다.


방법 1. Arrays 클래스의 equals 메서드

Arrays 클래스는 두 배열을 비교하는 equals() 메서드를 제공합니다.

 

equals() 메서드는 주소 값이 아닌 배열의 요소를 비교합니다.

 

두 배열이 동일한 타입, 동일한 수의 요소 그리고 정렬 순서가 동일한 경우 true를 반환하고 그렇지 않으면 false를 반환합니다.

 

다음 예제는 1부터 3까지 정수 값을 가지는 int 타입의 두 배열을 equals() 메서드로 비교합니다.

public static void main(String args[]) {
  int[] intArray1 = new int[] { 1, 2, 3 };
  int[] intArray2 = new int[] { 1, 2, 3 };

  if(Arrays.equals(intArray1, intArray2)) {
    System.out.println("두 배열은 동일합니다.");
  } else {
    System.out.println("두 배열은 동일하지 않습니다.");
  }
}

[실행 결과]

두 배열은 동일합니다.

방법 2. Arrays 클래스의 deepEquals 메서드

일차원 배열이 아닌 다차원 배열인 경우 equals() 메서드가 아닌 deepEquals() 메서드를 사용합니다.

 

다음 예제는 int 타입의 2차원 배열을 equals() 메서드와 deepEquals() 메서드를 사용하여 비교합니다.

public static void main(String args[]) {
  int[][] intArray1 = new int[][] 
  {
    {1, 2},
    {3, 4},
    {5, 6}
  };

  int[][] intArray2 = new int[][] 
  {
    {1, 2},
    {3, 4},
    {5, 6}
  };

  System.out.println("Arrays.equals() 메서드의 결과: " + 
          Arrays.equals(intArray1, intArray2));
          
  System.out.println("Arrays.deepEquals() 메서드의 결과: " + 
          Arrays.deepEquals(intArray1, intArray2));
}

[실행 결과]

Arrays.equals() 메서드의 결과: false
Arrays.deepEquals() 메서드의 결과: true

방법 3. 사용자 정의 클래스

배열의 타입이 사용자가 정의한 클래스 타입인 경우에는 두 배열을 비교하는 방법이 생각보다 복잡합니다.

 

다음 소스 코드는 사용자가 직접 정의한 Person 클래스입니다.

public class Person {
  private String Name;
  private Integer Age;

  public Person(String name, Integer age) {
    Name = name;
    Age = age;
  }

  public String getName() {
    return Name;
  }

  public void setName(String name) {
    Name = name;
  }

  public Integer getAge() {
    return Age;
  }

  public void setAge(Integer age) {
    this.Age = age;
  }
}

그리고 Person 타입의 두 배열을 비교하기 위해 equals() 메서드와 deepEquals() 메서드를 호출합니다.

public static void main(String args[]) {
  Person[] personArray1 = new Person[] {
    new Person("둘리", 20),
    new Person("또치", 30)
  };

  Person[] personArray2 = new Person[] {
    new Person("둘리", 20),
    new Person("또치", 30)
  };

  System.out.println("Arrays.equals() 메서드의 결과: " +
          Arrays.equals(personArray1, personArray2));

  System.out.println("Arrays.deepEquals() 메서드의 결과: " +
          Arrays.deepEquals(personArray1, personArray2));
}

[실행 결과]

Arrays.equals() 메서드의 결과: false
Arrays.deepEquals() 메서드의 결과: false

제일 위에서 언급했듯이 주소 값이 아닌 기본 값을 비교해야 하는데, 배열의 요소가 객체이므로 주소 값을 비교하게 됩니다.

 

사용자 정의 클래스 타입인 두 배열을 비교하려면, equals() 메서드와 hashCode() 메서드를 재정의합니다.

 

다음 소스 코드는 Person 타입의 두 배열이 객체의 Name, Age 필드를 비교하도록 equlas() 메서드와 hashCode() 메서드를 재정의합니다.

public class Person {
  // 필드 및 프로퍼티는 위 소스 코드와 동일함...
  @Override
  public boolean equals(Object o) {
    if (this == o)
      return true;
    if (o == null || getClass() != o.getClass())
      return false;
    Person person = (Person) o;
    return Objects.equals(Name, person.getName()) && Objects.equals(Age, person.getAge());
  }

  @Override
  public int hashCode() {
    return Objects.hash(Name, Age);
  }
}

이제, Person 타입의 두 배열이 동일한지 확인하기 위해 equals() 메서드와 deepEquals() 메서드를 호출합니다.

public static void main(String args[]) {
  Person[] personArray1 = new Person[] {
    new Person("둘리", 20),
    new Person("또치", 30)
  };

  Person[] personArray2 = new Person[] {
    new Person("둘리", 20),
    new Person("또치", 30)
  };

  System.out.println("Arrays.equals() 메서드의 결과: " +
          Arrays.equals(personArray1, personArray2));

  System.out.println("Arrays.deepEquals() 메서드의 결과: " +
          Arrays.deepEquals(personArray1, personArray2));
}

[실행 결과]

Arrays.equals() 메서드의 결과: true
Arrays.deepEquals() 메서드의 결과: true

마지막으로 객체의 필드 값이 다른 경우 false를 반환하는지 확인해봅시다.

 

두 배열은 두 번째 요소의 Age 필드의 값이 다르므로 false가 반환됩니다.

public static void main(String args[]) {
  Person[] personArray1 = new Person[] {
    new Person("둘리", 20),
    new Person("또치", 30)
  };

  Person[] personArray2 = new Person[] {
    new Person("둘리", 20),
    new Person("또치", 100)
  };

  System.out.println("Arrays.equals() 메서드의 결과: " +
          Arrays.equals(personArray1, personArray2));

  System.out.println("Arrays.deepEquals() 메서드의 결과: " +
          Arrays.deepEquals(personArray1, personArray2));
}

[실행 결과]

Arrays.equals() 메서드의 결과: false
Arrays.deepEquals() 메서드의 결과: false
반응형

댓글