Java에서 배열 비교

1. 개요

이 튜토리얼에서는 Java에서 배열을 비교하는 다양한 방법을 살펴볼 것 입니다. 일반적인 방법을 다루고 람다 표현식을 사용하는 몇 가지 예도 살펴 보겠습니다 .

2. 어레이 비교

우리는 자바에서 배열을 비교할 것입니다. 우리가 알고 있듯이 이것들은 객체입니다. 따라서 몇 가지 기본 개념을 새로 고쳐 보겠습니다.

  • 개체에는 참조와 값이 있습니다.
  • 두 개의 동일한 참조는 동일한 값을 가리켜 야합니다.
  • 서로 다른 두 값은 서로 다른 참조를 가져야합니다.
  • 두 개의 동일한 값이 반드시 동일한 참조를 갖는 것은 아닙니다.
  • 기본 값은 값별로 만 비교됩니다.
  • 문자열 리터럴은 값별로 만 비교됩니다.

2.1. 개체 참조 비교

동일한 배열을 가리키는 두 개의 참조가있는 경우 == 연산자를 사용한 같음 비교에서 항상 결과가 이어야합니다 .

예를 살펴 보겠습니다.

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = planes1;

먼저 planes1이 참조하는 평면 모델 배열을 만들었습니다 . 그런 다음 planes1 을 참조하는 planes2 를 생성 합니다. 이렇게함으로써 우리는 memory에 동일한 배열에 대한 두 개의 참조 생성 합니다 . 따라서 "planes1 == planes2" 표현식은 true 를 반환 합니다 .

배열의 경우 equals () 메서드는 == operator와 동일합니다 . 따라서 planes1.equals (planes2) 는 두 참조가 동일한 객체를 참조하기 때문에 true를 반환 합니다. 일반적으로 array1.eqauls (array2)array1 == array2 ″ 표현식이 true 를 반환하는 경우에만 true를 반환 합니다 .

두 참조가 동일한 지 확인합시다.

assertThat(planes1).isSameAs(planes2);

이제 planes1 이 참조하는 값이 planes2 가 참조하는 값 과 실제로 동일한 지 확인 하겠습니다 . 따라서 planes2가 참조하는 배열을 변경하고 변경 사항이 planes1이 참조하는 배열에 영향을 미치는지 확인할 수 있습니다 .

planes2[0] = "747";

마침내 이것이 작동하는지 확인하기 위해 우리의 주장을 해보자 :

assertThat(planes1).isSameAs(planes2); assertThat(planes2[0]).isEqualTo("747"); assertThat(planes1[0]).isEqualTo("747");

이 단위 테스트를 통해 두 배열을 참조로 비교할 수있었습니다.

그러나 한 참조가 다른 값에 할당되면 동일한 값을 참조 한다는 것만 증명했습니다 .

이제 동일한 값을 가진 두 개의 서로 다른 배열을 만듭니다.

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };

그것들은 다른 물체이기 때문에 우리는 그것들이 동일하지 않다는 것을 확실히 알고 있습니다. 따라서 다음과 같이 비교할 수 있습니다.

assertThat(planes1).isNotSameAs(planes2);

요약하면,이 경우 정확히 동일한 순서로 동일한 문자열 값 을 포함하는 두 개의 배열이 메모리에 있습니다 . 그러나 참조 된 배열의 내용이 다를뿐만 아니라 참조 자체도 다릅니다.

2.2. 어레이 길이 비교

배열의 길이는 요소 유형 또는 값이 채워 졌는지 여부에 관계없이 비교할 수 있습니다 .

두 개의 배열을 만들어 보겠습니다.

final String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; final Integer[] quantities = new Integer[] { 10, 12, 34, 45, 12, 43, 5, 2 };

이들은 요소 유형이 다른 두 개의 서로 다른 배열입니다. 이 데이터 세트에서는 예를 들어 각 모델의 비행기가 창고에 저장되어있는 수를 등록합니다. 이제 단위 테스트를 실행 해 보겠습니다.

assertThat(planes1).hasSize(8); assertThat(quantities).hasSize(8);

이를 통해 두 배열 모두에 8 개의 요소가 있고 length 속성이 각 배열에 대해 올바른 수의 요소를 반환 함을 입증했습니다 .

2.3. Arrays.equals 와 배열 비교

지금까지 우리는 객체 ID를 기준으로 배열을 비교했습니다. 반면에 두 배열이 내용면에서 동일한 지 확인하기 위해 Java는 Arrays.equals 정적 메소드를 제공합니다 . 이 메서드는 배열을 위치별로 병렬로 반복 하고 모든 요소 쌍에 대해 == 연산자를 적용합니다 .

정확히 동일한 순서로 동일한 문자열 리터럴을 사용하여 두 개의 서로 다른 배열을 만들어 보겠습니다 .

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };

그리고 이제 그들이 동등하다고 주장합시다.

assertThat(Arrays.equals(planes1, planes2)).isTrue();

두 번째 배열 값의 순서를 변경하면 :

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" }; String[] planes2 = new String[] { "B738", "A320", "A321", "A319", "B77W", "B737", "A333", "A332" }; 

다른 결과를 얻을 수 있습니다.

assertThat(Arrays.equals(planes1, planes2)).isFalse();

2.4. Arrays.deepEquals 와 배열 비교

== 연산자를 사용하는 것은 Java에서 간단한 유형을 사용하는 경우 쉽습니다 . 기본 유형 또는 문자열 리터럴 일 수 있습니다 . Object 배열 간의 비교는 더 복잡 할 수 있습니다. 그 이유는 Arrays.deepEquals 기사 에 자세히 설명되어 있습니다. 예를 봅시다.

먼저 Plane 클래스 부터 시작하겠습니다 .

public class Plane { private final String name; private final String model; // getters and setters }

그리고 hashCodeequals 메소드를 구현해 보겠습니다 .

@Override public boolean equals(Object o)  if (this == o) return true; if (o == null  @Override public int hashCode() { return Objects.hash(name, model); }

둘째, 다음의 2 개 요소 배열을 만들어 보겠습니다.

Plane[][] planes1 = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }}; Plane[][] planes2 = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }}; 

이제 그들이 참인지, 매우 동일한 배열인지 살펴 보겠습니다.

assertThat(Arrays.deepEquals(planes1, planes2)).isTrue();

To make sure that our comparison works as expected, let's now change the order of our last array:

Plane[][] planes1 = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }}; Plane[][] planes2 = new Plane[][] { new Plane[]{new Plane("Plane 2", "B738")}, new Plane[]{new Plane("Plane 1", "A320") }};

Finally, let's test if they are indeed not equal anymore:

assertThat(Arrays.deepEquals(planes1, planes2)).isFalse();

2.5. Comparing Arrays with Different Orders of Elements

To check if arrays are equal, regardless of the order of elements, we need to define what makes one instance of our Plane unique. For our case, a different name or model is enough to determine that one plane is different from another. We've established this by having already implemented both hashCode and equals methods. This implies that before we can compare our arrays, we should sort them. For that, we need a Comparator:

Comparator planeComparator = (o1, o2) -> { if (o1.getName().equals(o2.getName())) { return o2.getModel().compareTo(o1.getModel()); } return o2.getName().compareTo(o1.getName()); };

In this Comparator, we're giving priority to the name. If the names are equal, we solve the ambiguity by looking at the model. We compare strings by using the compareTo method of type String.

We want to be able to find if arrays are equal regardless of the sorting order. To do that, let's now sort our arrays:

Arrays.sort(planes1[0], planeComparator); Arrays.sort(planes2[0], planeComparator);

And finally, let's test them:

assertThat(Arrays.deepEquals(planes1, planes2)).isTrue();

Having sorted the arrays in the same order first, we allow the deepEquals method to find if these two arrays are equal.

3. Conclusion

이 튜토리얼에서 우리는 배열을 비교하는 다양한 방법을 보았습니다. 둘째, 참조와 값을 비교하는 것의 차이를 확인했습니다. 또한 배열을 심도있게 비교할 수있는 방법을 살펴 보았습니다 . 마지막으로 equalsdeepEquals를 사용하여 일반 비교와 심층 비교의 차이를 확인했습니다 .

항상 그렇듯이 예제의 전체 소스 코드는 GitHub에서 사용할 수 있습니다.