Java에서 equals vs Arrays.equals


209

Java에서 배열을 비교할 때 다음 두 문 사이에 차이점이 있습니까?

Object[] array1, array2;
array1.equals(array2);
Arrays.equals(array1, array2);

그렇다면 그렇다면 무엇입니까?


([] A1, 객체 [] A2를 개체) java.util.Arrays.deepEquals로도 봐
ultraon

답변:


299

array1.equals(array2)와 동일합니다 array1 == array2. 즉 같은 배열입니다. @alf가 지적했듯이 대부분의 사람들이 기대하는 것은 아닙니다.

Arrays.equals(array1, array2) 배열의 내용을 비교합니다.


비슷하게 array.toString()유용하지 않을 수 있으므로 사용해야 Arrays.toString(array)합니다.


59
참고 Arrays.equals()다차원 배열 예상대로 작동하지 않습니다, 그것은 단지 참조 평등에 대한 1 차원의 항목을 비교합니다. Apache commons ArrayUtils.isEquals는 다차원 배열에서 작동합니다.
Adam Parkin

4
나는 기절했다. 길이와 모든 객체를 비교하는 대신 포인터 비교를 위해 array.equals를 구현 해야하는 이유가 있습니까?
Lake

2
@Lake는 배열 길이와 포함 된 객체를 비교하지만 수행하지 않는 것은 깊은 비교입니다. 사실 equals는 배열에 대한 예상대로 작동하지 않으므로 처음에는 문제가되지 않습니다.
Peter Lawrey

48
우리가 가지고있는 이유입니다 @AdamParkin Arrays.deepEquals(Object[], Object[]).
Elliott Frisch

3
@JeewanthaSamaraweera는 그 방법에 대한 정의이지만 .equals내용을 비교하지 않기 때문에 그 방법이 필요합니다.
Peter Lawrey

86

그것은 악명 높은 문제입니다. .equals()배열이 심하게 손상되었으므로 사용하지 마십시오.

그것은 "누군가가 실제로 잘못한 것"과 같이 "파손 된"것이 아니라 정의 된 것과 보통 예상되는 것을하지 않는 것입니다. 그래서 순수 주의자들에게는 : 그것은 완벽하게 괜찮 습니다.

이제 예상되는 동작 equals은 데이터를 비교하는 것입니다. 기본 동작은 Object데이터가없는 것처럼 신원을 비교하는 것입니다 (순수 자의 경우 : 그렇습니다. equals서브 클래스에서 필요한 경우 구현한다고 가정 합니다. 배열에는 구현이 없으므로 사용하지 않아야합니다.

따라서 차이점은 예상대로Arrays.equals(array1, array2) 작동합니다 (예 : 내용 비교). 다시 구현으로 넘어 가서 정체성을 비교하므로 (순수 주의자 : 예 나는 알고 있습니다 ).array1.equals(array2)Object.equals==null

문제는 Arrays.equals(array1, array2)배열의 요소가 equals제대로 구현 되지 않으면 열심히 물릴 것 입니다. 나는 매우 순진한 진술이지만, 명백히 덜 중요한 경우가 있습니다 .2D 배열을 고려하십시오.

Java의 2D 배열은 배열의 배열이며 배열 equals은 깨지거나 원하는 경우 쓸모 Arrays.equals(array1, array2)가 없으므로 2D 배열에서 예상대로 작동하지 않습니다.

희망이 도움이됩니다.


13
그것은 깨지지 않았으며 단지 Object에서 상속되었습니다.
Michael Borgwardt

배열에 대한 사용자 정의 구현이 equals()있습니까? Object에서 재정의되지 않았다고 생각했습니다.
Martijn Courteaux

@MichaelBorgwardt 그것은 javadoc에서 말한 것을하지 않는 방법을 가진 시스템 라이브러리입니다. 나에게 충분히 부서진 소리. 즉, 나는 그것이 매우 논쟁의 여지가있는 진술이라는 것을 인정하지만, 그것이 "깨져있다"는 것이 더 잘 기억된다고 생각하므로, 이런 식으로 생각하는 것이 훨씬 더 편리합니다.
alf

@MartijnCourteaux 그것은 정확히 문제입니다 :)
alf

3
배열의 배열의 경우, 필요 Arrays.deepEquals가 무엇 --- someArray.equals모두 함께 수행해야합니다. (관련 : Objects.deepEquals.)
Kevin J. Chase

16

두 가지 방법의 구현을 살펴보고 깊이 이해하십시오.

array1.equals(array2);
/**
 * Indicates whether some other object is "equal to" this one.
 * <p>
 * The {@code equals} method implements an equivalence relation
 * on non-null object references:
 * <ul>
 * <li>It is <i>reflexive</i>: for any non-null reference value
 *     {@code x}, {@code x.equals(x)} should return
 *     {@code true}.
 * <li>It is <i>symmetric</i>: for any non-null reference values
 *     {@code x} and {@code y}, {@code x.equals(y)}
 *     should return {@code true} if and only if
 *     {@code y.equals(x)} returns {@code true}.
 * <li>It is <i>transitive</i>: for any non-null reference values
 *     {@code x}, {@code y}, and {@code z}, if
 *     {@code x.equals(y)} returns {@code true} and
 *     {@code y.equals(z)} returns {@code true}, then
 *     {@code x.equals(z)} should return {@code true}.
 * <li>It is <i>consistent</i>: for any non-null reference values
 *     {@code x} and {@code y}, multiple invocations of
 *     {@code x.equals(y)} consistently return {@code true}
 *     or consistently return {@code false}, provided no
 *     information used in {@code equals} comparisons on the
 *     objects is modified.
 * <li>For any non-null reference value {@code x},
 *     {@code x.equals(null)} should return {@code false}.
 * </ul>
 * <p>
 * The {@code equals} method for class {@code Object} implements
 * the most discriminating possible equivalence relation on objects;
 * that is, for any non-null reference values {@code x} and
 * {@code y}, this method returns {@code true} if and only
 * if {@code x} and {@code y} refer to the same object
 * ({@code x == y} has the value {@code true}).
 * <p>
 * Note that it is generally necessary to override the {@code hashCode}
 * method whenever this method is overridden, so as to maintain the
 * general contract for the {@code hashCode} method, which states
 * that equal objects must have equal hash codes.
 *
 * @param   obj   the reference object with which to compare.
 * @return  {@code true} if this object is the same as the obj
 *          argument; {@code false} otherwise.
 * @see     #hashCode()
 * @see     java.util.HashMap
 */
public boolean equals(Object obj) {
    return (this == obj);
}

동안:

Arrays.equals(array1, array2);
/**
 * Returns <tt>true</tt> if the two specified arrays of Objects are
 * <i>equal</i> to one another.  The two arrays are considered equal if
 * both arrays contain the same number of elements, and all corresponding
 * pairs of elements in the two arrays are equal.  Two objects <tt>e1</tt>
 * and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null
 * : e1.equals(e2))</tt>.  In other words, the two arrays are equal if
 * they contain the same elements in the same order.  Also, two array
 * references are considered equal if both are <tt>null</tt>.<p>
 *
 * @param a one array to be tested for equality
 * @param a2 the other array to be tested for equality
 * @return <tt>true</tt> if the two arrays are equal
 */
public static boolean equals(Object[] a, Object[] a2) {
    if (a==a2)
        return true;
    if (a==null || a2==null)
        return false;

    int length = a.length;
    if (a2.length != length)
        return false;

    for (int i=0; i<length; i++) {
        Object o1 = a[i];
        Object o2 = a2[i];
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }

    return true;
}

11

한숨. 70 년대에는 IBM 370 시스템의 "시스템 프로그래머"(sysadmin) 였고, 고용주는 IBM 사용자 그룹 SHARE의 구성원이었습니다. 누군가가 일부 CMS 명령의 예기치 않은 동작에 대해 APAR (버그 보고서)을 제출 한 경우가있을 수 있으며 IBM은 NOTABUG로 응답합니다.

SHARE는 BAD-Broken As Designed에 대한 카운터를 제시했습니다. 이것이 배열의 equals 구현에 적용될 수 있다고 생각합니다.

Object.equals 구현에는 아무런 문제가 없습니다. 개체에 데이터 멤버가 없으므로 비교할 것이 없습니다. 두 개의 "Object"는 실제로 동일한 Object (내부적으로 동일한 주소 및 길이) 인 경우에만 동일합니다.

그러나 해당 논리는 배열에는 적용되지 않습니다. 배열에는 데이터가 있으며 데이터를 비교하기 위해 (등을 통해) 비교를 기대합니다. 이상적으로 Arrays.deepEquals와 같은 방식이지만 최소한 Arrays.equals와 같은 방식 (요소의 얕은 비교).

따라서 문제는 배열 (내장 객체)이 Object.equals를 재정의하지 않는다는 것입니다. (명명 된 클래스로) 문자열 않습니다 오버라이드 Object.equals을 당신이 기대하는 결과를 제공합니다.

주어진 다른 대답은 정확합니다. [...]. equals ([....])는 단순히 내용이 아닌 포인터를 비교합니다. 아마 언젠가 누군가가 이것을 고칠 것입니다. 아니면 어쩌면 : [...]. equals가 실제로 요소를 비교하면 몇 개의 기존 프로그램이 중단됩니까? 많지는 않지만 나는 0보다 큰 것으로 생각합니다.


5
나는 Broken.As.Designed 약어를 좋아합니다
Chris

5

배열 equals()Object 따라서 및 자체에 대한 배열을 비교하는 경우에만 true를 돌려주는 비교할 수 있습니다.

반면에 Arrays.equals 배열의 요소를 비교합니다.

이 스 니펫은 차이점을 설명합니다.

Object o1 = new Object();
Object o2 = new Object();
Object[] a1 = { o1, o2 };
Object[] a2 = { o1, o2 };
System.out.println(a1.equals(a2)); // prints false
System.out.println(Arrays.equals(a1, a2)); // prints true

도 참조하십시오 Arrays.equals(). 관심있는 또 다른 정적 방법은 다음과 같습니다 Arrays.deepEquals()..


1

그만큼 Arrays.equals(array1, array2):

두 배열에 같은 수의 요소가 포함되어 있고 두 배열의 모든 해당 요소 쌍이 같은지 확인하십시오.

그만큼 array1.equals(array2):

객체를 다른 객체와 비교하고 두 객체의 참조가 Object.equals()


0

equals()배열이에서 상속 Object는 arrrays의 내용을 보지 않도록, 그것은 각 배열 자체에 동일 간주합니다.

Arrays.equals()방법은 않습니다 배열 '의 내용을 비교합니다. 모든 기본 유형에 대한 과부하가 있으며 객체에 대한 유형은 객체 자체의 equals()메소드를 사용합니다 .


2
"배열의 내용"이라고하면 다차원 배열도 의미합니까?
AlanFoster

@AlanFoster : 아니오. 다차원 배열은 배열의 배열입니다. 즉, Arrays.equals (Object [], Object []) 메소드가 호출되어 하위 배열의 equals () 메소드를 호출합니다.
Michael Borgwardt

0
import java.util.Arrays;
public class ArrayDemo {
   public static void main(String[] args) {
   // initializing three object arrays
   Object[] array1 = new Object[] { 1, 123 };
   Object[] array2 = new Object[] { 1, 123, 22, 4 };
   Object[] array3 = new Object[] { 1, 123 };

   // comparing array1 and array2
   boolean retval=Arrays.equals(array1, array2);
   System.out.println("array1 and array2 equal: " + retval);
   System.out.println("array1 and array2 equal: " + array1.equals(array2));

   // comparing array1 and array3
   boolean retval2=Arrays.equals(array1, array3);
   System.out.println("array1 and array3 equal: " + retval2);
   System.out.println("array1 and array3 equal: " + array1.equals(array3));

   }
}

출력은 다음과 같습니다.

    array1 and array2 equal: false
    array1 and array2 equal: false

    array1 and array3 equal: true
    array1 and array3 equal: false

이런 종류의 문제를 보면서 Arrays.equals(array1, array2)혼란을 피하기 위해 귀하의 질문에 따라 개인적으로 갈 것 입니다.


올바른 것처럼 보이지만 배열에서는 요소의 순서도 중요합니다. 예를 들어, 다른 배열이 있다면 Object [] array4 = new Object [] {123, 1}; Arrays.equals (array3, array4)를 사용하면 false를 반환합니다.
jiahao
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.