2012-01-08 11 views

Trả lời

249

array1.equals(array2) giống với array1 == array2, tức là cùng một mảng. Như @alf chỉ ra nó không phải là những gì hầu hết mọi người mong đợi.

Arrays.equals(array1, array2) so sánh nội dung của các mảng.


Tương tự array.toString() có thể không hữu ích và bạn cần sử dụng Arrays.toString(array).

+48

Lưu ý rằng 'Arrays.equals()' không hoạt động như mong đợi đối với mảng đa chiều, nó chỉ so sánh các mục của thứ nguyên thứ nhất cho bình đẳng tham chiếu. Apache commons 'ArrayUtils.isEquals' làm việc với các mảng đa chiều. –

+3

Tôi choáng váng. Có một lý do cho array.equals được thực hiện để so sánh con trỏ chứ không phải là so sánh chiều dài và mọi đối tượng? – Lake

+2

@Lake so sánh chiều dài mảng và các đối tượng chứa, nhưng những gì nó không làm là so sánh sâu. Thực tế bằng không hoạt động như mong đợi đối với mảng bị hỏng, đây không phải là vấn đề ở nơi đầu tiên. –

71

Đó là một vấn đề khét tiếng: .equals() cho mảng bị hỏng nặng, chỉ cần không sử dụng nó, bao giờ hết.

Điều đó nói rằng, nó không "hỏng" như trong "ai đó đã làm điều đó một cách thực sự sai" - nó chỉ làm những gì được xác định và không phải những gì thường được mong đợi. Vì vậy, đối với những người theo chủ nghĩa thuần túy: nó hoàn toàn ổn, và điều đó cũng có nghĩa là, không sử dụng nó, bao giờ hết.

Hiện hành vi mong đợi cho equals là so sánh dữ liệu. Hành vi mặc định là so sánh danh tính, vì Object không có bất kỳ dữ liệu nào (cho thuần túy: có nó có, nhưng nó không phải là điểm); giả định là, nếu bạn cần equals trong các lớp con, bạn sẽ triển khai nó. Trong mảng, không có triển khai cho bạn, vì vậy bạn không được phép sử dụng nó.

Vì vậy, sự khác biệt là, Arrays.equals(array1, array2) làm việc như bạn mong chờ (tức là so sánh nội dung), array1.equals(array2) rơi trở lại Object.equals thực hiện, do đó so sánh bản sắc, và do đó tốt hơn thay thế bằng == (đối với chủ nghĩa thuần túy: yes tôi biết về null).

Vấn đề là, ngay cả Arrays.equals(array1, array2) sẽ cắn bạn khó nếu các thành phần của mảng không thực hiện đúng cách equals. Đó là một tuyên bố rất ngây thơ, tôi biết, nhưng có một trường hợp ít quan trọng hơn rất rõ ràng: xem xét một mảng 2D.

Mảng 2D trong Java là mảng mảng và mảng equals bị hỏng (hoặc vô ích nếu bạn thích), vì vậy Arrays.equals(array1, array2) sẽ không hoạt động như bạn mong đợi trên các mảng 2D.

Hy vọng điều đó sẽ hữu ích.

+11

Nó không bị hỏng, nó chỉ được thừa kế từ Object. –

+1

Không thực sự trả lời câu hỏi. Đây là một bình luận. – AlanFoster

+0

Một mảng có thực hiện tùy chỉnh cho 'equals()'? Tôi nghĩ là không bị đánh lừa bởi Object. –

0

equals() của mảng được kế thừa từ Object, do đó, nó không xem xét nội dung của các mảng, nó chỉ xem xét từng mảng bằng chính nó.

Phương thức Arrays.equals()do so sánh nội dung của mảng. Có quá tải cho tất cả các kiểu nguyên thủy, và một đối với các đối tượng sử dụng các phương thức riêng của equals() của các đối tượng.

+2

bạn nói "nội dung mảng", điều này có nghĩa là mảng đa chiều không? – AlanFoster

+0

@AlanFoster: no. Mảng đa chiều là các mảng của mảng, có nghĩa là phương thức Arrays.equals (Object [], Object []) sẽ được gọi, gọi các phương thức equals() của các mảng con là –

1

Các Arrays.equals(array1, array2):

kiểm tra nếu cả hai mảng chứa cùng một số yếu tố, và tất cả các cặp tương ứng của phần tử trong hai mảng đều bình đẳng.

Các array1.equals(array2):

so sánh các đối tượng để đối tượng khác và trở về đúng chỉ nếu tham chiếu của đối tượng hai đều bình đẳng như trong Mảng Object.equals()

5

kế thừa equals() từ Object và do đó so sánh chỉ trả về true nếu so sánh một mảng với chính nó.

Mặt khác, Arrays.equals so sánh các phần tử của mảng.

đoạn này elucidates sự khác biệt:

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 

Xem thêm Arrays.equals(). Một phương pháp tĩnh khác cũng có thể quan tâm: Arrays.deepEquals().

15

Nhìn bên trong việc thực hiện hai phương pháp để hiểu họ sâu sắc:

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); 
} 

khi:

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; 
} 
7

Sigh. Trở lại những năm 70, tôi là "lập trình viên hệ thống" (sysadmin) cho một hệ thống IBM 370, và chủ nhân của tôi là thành viên của nhóm người dùng IBM SHARE. Nó đôi khi sẽ xảy ra rằng ai đó đã gửi một APAR (báo cáo lỗi) về một số hành vi bất ngờ của một số lệnh CMS, và IBM sẽ trả lời NOTABUG: lệnh thực hiện những gì nó được thiết kế để làm (và những gì tài liệu nói).

SHARE đã đưa ra một bộ đếm này: BAD - Broken As Designed. Tôi nghĩ rằng điều này có thể áp dụng cho việc thực hiện này bằng cho mảng.

Không có gì sai với việc triển khai Object.equals. Đối tượng không có thành viên dữ liệu, vì vậy không có gì để so sánh. Hai "đối tượng" là bằng nhau nếu và chỉ khi chúng được, trên thực tế, cùng một đối tượng (nội bộ, cùng một địa chỉ và chiều dài).

Nhưng logic đó không áp dụng cho mảng. Mảng có dữ liệu và bạn mong đợi so sánh (thông qua bằng) để so sánh dữ liệu. Lý tưởng nhất là cách mà Arrays.deepEquals thực hiện, nhưng ít nhất là cách mà Arrays.equals thực hiện (so sánh nông của các phần tử).

Vì vậy, vấn đề là mảng (như một đối tượng tích hợp) không ghi đè Object.equals. Chuỗi (như một lớp có tên) hiện ghi đè Object.equals và cho kết quả bạn mong đợi.

Câu trả lời khác được đưa ra là chính xác: [...]. Bằng ([....]) chỉ cần so sánh con trỏ chứ không phải nội dung. Có lẽ một ngày nào đó ai đó sẽ sửa lỗi này. Hoặc có thể không: bao nhiêu chương trình hiện có sẽ bị hỏng nếu [...]. Bằng thực tế so sánh các phần tử? Không nhiều, tôi nghi ngờ, nhưng nhiều hơn không.

+2

Tôi thích từ viết tắt Broken.As.Designed – Chris

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

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

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

    } 
} 

Đây là kết quả:

arr1 and arr2 equal: false 
    arr1 and arr2 equal: false 

    arr1 and arr3 equal: true 
    arr1 and arr3 equal: false 

Thấy loại vấn đề cá nhân tôi sẽ đi cho Arrays.equals(array1, array2) theo câu hỏi của bạn để tránh nhầm lẫn.