Sự khác biệt giữa so sánh () và so sánhTo () là gì?


110

Sự khác biệt giữa Java's compare()compareTo()các phương thức là gì? Những phương pháp đó có đưa ra câu trả lời giống nhau không?


1
Bạn muốn so sánh Metode lớp nào?
Markus Lausberg

cho lời giải thích chi tiết trong những ứng dụng của cả hai so sánh () và compareTo (): sysdotoutdotprint.com/index.php/2017/03/28/...
mel3kings

Câu trả lời:


160

Từ JavaNotes :

  • a.compareTo(b):
    Giao diện có thể so sánh : So sánh các giá trị và trả về một int cho biết các giá trị được so sánh nhỏ hơn, bằng hay lớn hơn.
    Nếu các đối tượng lớp của bạn có thứ tự tự nhiên , hãy triển khai Comparable<T>giao diện và định nghĩa phương thức này. Tất cả các lớp Java có một trật tự tự nhiên thực hiện Comparable<T>- Ví dụ: String, lớp wrapper ,BigInteger

  • compare(a, b):
    Giao diện so sánh: So sánh giá trị của hai đối tượng. Điều này được triển khai như một phần của Comparator<T>giao diện và cách sử dụng điển hình là xác định một hoặc nhiều lớp tiện ích nhỏ thực hiện điều này, để chuyển cho các phương thức như sort()hoặc để sử dụng bằng cách sắp xếp các cấu trúc dữ liệu như TreeMapTreeSet . Bạn có thể muốn tạo một đối tượng Comparator để làm như sau:

    • Nhiều so sánh . Để cung cấp một số cách khác nhau để sắp xếp thứ gì đó. Ví dụ, bạn có thể muốn sắp xếp một lớp Person theo tên, ID, tuổi, chiều cao, ... Bạn sẽ xác định một Bộ so sánh cho từng thứ này để chuyển cho sort()phương thức.
    • Lớp hệ thống Để cung cấp các phương pháp so sánh cho các lớp mà bạn không có quyền kiểm soát. Ví dụ, bạn có thể xác định một Bộ so sánh cho các Chuỗi so sánh chúng theo độ dài.
    • Mẫu chiến lược Để triển khai một mẫu Chiến lược, là tình huống bạn muốn biểu diễn một thuật toán dưới dạng một đối tượng mà bạn có thể truyền dưới dạng tham số, lưu trong cấu trúc dữ liệu, v.v.

Nếu các đối tượng lớp của bạn có một thứ tự sắp xếp tự nhiên, bạn có thể không cần so sánh ().


Tổng hợp từ http://www.digizol.com/2008/07/java-sorting-comparator-vs-comp so sánh.html


thể so sánh Một đối tượng có thể so sánh được có khả năng so sánh chính nó với một đối tượng khác.

Bộ so sánh
Một đối tượng so sánh có khả năng so sánh hai đối tượng khác nhau. Lớp không so sánh các cá thể của nó, mà là một số cá thể của lớp khác.


Các ngữ cảnh trường hợp sử dụng:

Giao diện so sánh

Các bằng phương pháp và ==!= các nhà khai thác thử nghiệm cho sự bình đẳng / bất bình đẳng, nhưng không cung cấp một cách để kiểm tra cho các giá trị tương đối .
Một số lớp (ví dụ: Chuỗi và các lớp khác có thứ tự tự nhiên) triển khai Comparable<T>giao diện, định nghĩa một compareTo()phương thức.
Bạn sẽ muốn triển khai Comparable<T>trong lớp của mình nếu bạn muốn sử dụng nó với Collections.sort()hoặc Arrays.sort()các phương thức.

Xác định đối tượng Bộ so sánh

Bạn có thể tạo Bộ so sánh để sắp xếp bất kỳ cách nào tùy ý cho bất kỳ lớp nào .
Ví dụ, Stringlớp định nghĩa bộ CASE_INSENSITIVE_ORDERso sánh .


Sự khác biệt giữa hai cách tiếp cận có thể được liên kết với khái niệm về:
Bộ sưu tập có thứ tự :

Khi một Bộ sưu tập được đặt hàng, điều đó có nghĩa là bạn có thể lặp lại bộ sưu tập theo một thứ tự cụ thể (không phải ngẫu nhiên) (a Hashtablekhông được sắp xếp theo thứ tự).

Bộ sưu tập có thứ tự tự nhiên không chỉ được sắp xếp theo thứ tự mà còn được sắp xếp . Xác định một trật tự tự nhiên có thể khó khăn! (như theo thứ tự Chuỗi tự nhiên ).


Một sự khác biệt khác, được chỉ ra bởi HaveAGuess trong các bình luận :

  • Comparable đang trong quá trình triển khai và không hiển thị từ giao diện, vì vậy khi sắp xếp, bạn không thực sự biết điều gì sẽ xảy ra.
  • Comparator giúp bạn yên tâm rằng thứ tự sẽ được xác định rõ ràng.

2
Vì câu trả lời này là đầy đủ, đây là điều làm tôi khó chịu về So sánh mà bạn có thể muốn thêm: Nó đang được triển khai và không hiển thị từ giao diện, vì vậy khi bạn sắp xếp, bạn không thực sự biết điều gì sẽ xảy ra. Sử dụng công cụ so sánh giúp bạn yên tâm rằng thứ tự sẽ được xác định rõ ràng
HaveAGuess

@HaveAGuess điểm tốt. Tôi đã bao gồm bình luận của bạn trong câu trả lời để hiển thị nhiều hơn.
VonC

vật thể có trật tự tự nhiên, trật tự tự nhiên ở đây có nghĩa là gì? Một thành viên dữ liệu chuỗi cho ví dụ tên trong lớp nhân viên có thứ tự tự nhiên không ??
Narendra Jaggi

@NarendraJaggi Xem en.wikipedia.org/wiki/Enumeration . Một lệnh tạo điều kiện thuận lợi cho việc liệt kê. "Tự nhiên" theo nghĩa là một thứ tự tốt nhất định trên tập hợp chỉ mục cung cấp một cách duy nhất để liệt kê phần tử tiếp theo được liệt kê một phần
VonC

2
@VedantKekan Cảm ơn bạn. Tôi đã khôi phục 2 liên kết trong câu trả lời này.
VonC

16

compareTo()là từ Comparablegiao diện.

compare() là từ Comparatorgiao diện.

Cả hai phương pháp đều làm điều tương tự, nhưng mỗi giao diện được sử dụng trong một ngữ cảnh hơi khác nhau.

Các tính năng tương đương giao diện được sử dụng để áp đặt một trật tự tự nhiên trên các đối tượng của lớp thực hiện. Các compareTo()phương pháp được gọi là phương pháp so sánh tự nhiên. Các sánh giao diện được sử dụng để áp đặt một tổng trật tự trên các đối tượng của lớp thực hiện. Để biết thêm thông tin, hãy xem các liên kết để biết chính xác thời điểm sử dụng từng giao diện.


u có thể cho một số ví dụ? Cả hai phương pháp cho câu trả lời giống nhau?

Tôi không biết tại sao 'Có thể so sánh' là để đặt hàng tự nhiên? Chúng ta có thể tùy chỉnh nó, phải không?
c-an

14

Điểm giống nhau:
Cả hai đều là cách tùy chỉnh để so sánh hai đối tượng.
Cả hai đều trả về một intmô tả mối quan hệ giữa hai đối tượng.

Sự khác biệt: Phương thức compare()là một phương thức mà bạn bắt buộc phải triển khai nếu bạn triển khai Comparatorgiao diện. Nó cho phép bạn chuyển hai đối tượng vào phương thức và nó trả về một intmô tả mối quan hệ của chúng.

Comparator comp = new MyComparator();
int result = comp.compare(object1, object2);

Phương thức compareTo()là một phương thức mà bạn bắt buộc phải triển khai nếu bạn triển khai Comparablegiao diện. Nó cho phép một đối tượng được so sánh với các đối tượng cùng loại.

String s = "hi";
int result = s.compareTo("bye");

Tóm lại:
Về cơ bản chúng là hai cách khác nhau để so sánh mọi thứ.


9

Các phương pháp không nhất thiết phải đưa ra các câu trả lời giống nhau. Điều đó phụ thuộc vào đối tượng / lớp nào bạn gọi chúng.

Nếu bạn đang triển khai các lớp của riêng mình mà bạn biết rằng bạn muốn so sánh ở một số giai đoạn, bạn có thể yêu cầu chúng triển khai giao diện So sánh và triển khai phương thức CompareTo () cho phù hợp.

Nếu bạn đang sử dụng một số lớp từ một API không triển khai giao diện Có thể so sánh, nhưng bạn vẫn muốn so sánh chúng. Tức là để phân loại. Bạn có thể tạo lớp của riêng mình để triển khai giao diện Bộ so sánh và trong phương thức so sánh () của nó, bạn triển khai logic.


3

Giao diện so sánh chứa một phương thức được gọi là phương thức compareTo(obj)chỉ nhận một đối số và nó tự so sánh với một thể hiện hoặc các đối tượng khác của cùng một lớp.

Giao diện so sánh chứa một phương thức được gọi là phương thức compare(obj1,obj2)nhận hai đối số và nó so sánh giá trị của hai đối tượng từ các lớp giống nhau hoặc khác nhau.


3
compareTo(T object)

đến từ giao diện java.lang.Comp so sánh được, được triển khai để so sánh đối tượng này với đối tượng khác để cung cấp giá trị int âm cho đối tượng này nhỏ hơn, 0 đối với bằng hoặc giá trị dương lớn hơn đối tượng kia. Đây là phương pháp so sánh thuận tiện hơn, nhưng phải được thực hiện trong mọi lớp bạn muốn so sánh.

compare(T obj1, T obj2)

đến từ giao diện java.util.Comparator, được triển khai trong một lớp riêng biệt để so sánh các đối tượng của lớp khác để cung cấp giá trị int âm cho đối tượng đầu tiên nhỏ hơn, 0 cho bằng hoặc giá trị dương cho lớn hơn đối tượng thứ hai. Nó là cần thiết khi bạn không thể tạo một lớp triển khai CompareTo () vì nó không thể sửa đổi. Nó cũng được sử dụng khi bạn muốn có nhiều cách khác nhau để so sánh các đối tượng, không chỉ một (chẳng hạn như theo tên hoặc tuổi).


3

Sử dụng Comparator, chúng ta có thể có n số logic so sánh được viết cho một lớp .

Ví dụ

Đối với một hạng xe

Chúng ta có thể có một lớp So sánh để so sánh dựa trên số kiểu xe. Chúng tôi cũng có thể có một lớp So sánh để so sánh dựa trên năm mẫu xe.

Hạng ô tô

public class Car  {

    int modelNo;

    int modelYear;

    public int getModelNo() {
        return modelNo;
    }

    public void setModelNo(int modelNo) {
        this.modelNo = modelNo;
    }

    public int getModelYear() {
        return modelYear;
    }

    public void setModelYear(int modelYear) {
        this.modelYear = modelYear;
    }

}

Bộ so sánh số 1 dựa trên Mẫu số

public class CarModelNoCompartor implements Comparator<Car>{

    public int compare(Car o1, Car o2) {

        return o1.getModelNo() - o2.getModelNo();
    }

}

Bộ so sánh số 2 dựa trên Năm mẫu

public class CarModelYearComparator implements Comparator<Car> {

    public int compare(Car o1, Car o2) {

        return o1.getModelYear() - o2.getModelYear();
    }

}

Nhưng điều này không thể xảy ra với trường hợp So sánh giao diện .

Trong trường hợp của giao diện So sánh, chúng ta chỉ có thể có một logic trong phương thức CompareTo () .


2

Mối quan hệ của đối tượng có phương thức này và các cộng tác viên của nó là khác nhau.

compareTo()là một phương thức của giao diện Có thể so sánh , vì vậy nó được sử dụng để so sánh trường hợp NÀY với trường hợp khác.

compare()là một phương thức của interface Comparator , vì vậy nó được sử dụng để so sánh hai trường hợp khác nhau của một lớp khác với nhau.

Nếu bạn muốn, việc triển khai Comparablecó nghĩa là các thể hiện của lớp có thể được so sánh dễ dàng.
Việc thực thi Comparatorcó nghĩa là các cá thể phù hợp để so sánh các đối tượng khác nhau (của các lớp khác).


2

Sự khác biệt chính là trong việc sử dụng các giao diện:

So sánh được (trong đó có CompareTo ()) yêu cầu các đối tượng được so sánh (để sử dụng Sơ đồ cây hoặc để sắp xếp danh sách) để triển khai giao diện đó. Nhưng điều gì sẽ xảy ra nếu lớp không triển khai So sánh được và bạn không thể thay đổi nó vì nó là một phần của thư viện bên thứ ba? Sau đó, bạn phải triển khai Bộ so sánh, cách sử dụng này hơi kém thuận tiện hơn.


2

compareTo()được gọi trên một đối tượng, để so sánh nó với một đối tượng khác. compare()được gọi trên một số đối tượng để so sánh hai đối tượng khác.

Sự khác biệt là nơi logic so sánh thực tế được xác định.


Không phải những gì tôi muốn gọi là một câu trả lời tuyệt vời, nhưng tôi không nghĩ nó xứng đáng nhận được sự ủng hộ.
Paul Tomblin

Đồng ý, cá nhân tôi dành phiếu phản đối cho những câu trả lời sai hoặc gây hiểu lầm. Điều này chắc chắn là chính xác.
Joachim Sauer

Vậy những người 'thân thiện' đã từ chối tôi ở đâu? Đây là câu trả lời đúng thứ hai của tôi đã bị phản đối vì ai đó đã bỏ sót điểm. Hoặc là quan điểm không đồng tình hoặc quan điểm của câu trả lời của tôi. Cuộc sống thật tàn nhẫn .. ;-)
Abgan

0

Khi bạn muốn sắp xếp một Danh sách bao gồm Foo đối tượng, lớp Foo phải triển khai giao diện So sánh được, vì cách sắp xếp của Danh sách đang sử dụng methode này.

Khi bạn muốn viết một lớp Util để so sánh hai lớp khác, bạn có thể triển khai lớp So sánh.


0


Tên bảng nhân viên , DoB, Lương
Tomas, 2/10/1982, 300
Daniel, 3/11/1990, 400
Kwame, 2/10/1998, 520

Các tính năng tương đương giao diện cho phép bạn sắp xếp một danh sách các đối tượng ví dụ như nhân viên với tham chiếu đến một lĩnh vực chính - ví dụ, bạn có thể sắp xếp theo tên hoặc bằng lương với CompareTo () phương pháp

emp1.getName().compareTo(emp2.getName())

Giao diện linh hoạt hơn cho các yêu cầu như vậy được cung cấp bởi giao diện Bộ so sánh , có phương thức duy nhất là so sánh ()

public interface Comparator<Employee> {
 int compare(Employee obj1, Employee obj2);
}

Mã mẫu

public class NameComparator implements Comparator<Employee> {

public int compare(Employee e1, Employee e2) {
     // some conditions here
        return e1.getName().compareTo(e2.getName()); // returns 1 since (T)omas > (D)an 
    return e1.getSalary().compareTo(e2.getSalary()); // returns -1 since 400 > 300
}

}


0

Một điểm nữa:

  • compareTo()là từ Comparablegiao diện và compare()là từ Comparatorgiao diện.
  • Comparableđược sử dụng để xác định thứ tự mặc định cho các đối tượng trong một lớp trong khi Comparatorđược sử dụng để xác định thứ tự tùy chỉnh sẽ được chuyển đến một phương thức.

0

Có một khía cạnh kỹ thuật cũng cần được nhấn mạnh. Giả sử bạn cần tham số hóa hành vi so sánh từ một lớp máy khách và bạn đang phân vân nên sử dụng Comparablehay Comparatorcho một phương thức như thế này:

class Pokemon {
    int healthPoints;
    int attackDamage;
    public void battle (Comparable<Pokemon> comparable, Pokemon opponent) {
        if (comparable.compareTo(opponent) > 0) { //comparable needs to, but cannot, access this.healthPoints for example
            System.out.println("battle won");
        } else {
            System.out.println("battle lost");
        }
    }
}

comparablesẽ là lambda hoặc một đối tượng, và không có cách nào comparableđể truy cập vào các trường thisPokemon. (Trong lambda, thistham chiếu đến cá thể lớp ngoài trong phạm vi của lambda, như được định nghĩa trong văn bản chương trình.) Vì vậy, điều này không bay , và chúng ta phải sử dụng a Comparatorvới hai đối số.


0

Sử dụng giao diện So sánh để sắp xếp trên cơ sở nhiều giá trị như tuổi, tên, tên_tên ... Đối với một giá trị, hãy sử dụng giao diện So sánh


-2
Important Answar
String name;
int roll;

public int compare(Object obj1,Object obj2) { // For Comparator interface
    return obj1.compareTo(obj1);
}

public int compareTo(Object obj1) { // For Comparable Interface
    return obj1.compareTo(obj);
}

Ở đây trong return obj1.compareTo(obj1)hoặc return obj1.compareTo(obj)câu lệnh chỉ lấy Object; nguyên thủy không được phép. Ví dụ

name.compareTo(obj1.getName()) // Correct Statement.

Nhưng

roll.compareTo(obj1.getRoll()) 
// Wrong Statement Compile Time Error Because roll 
// is not an Object Type, it is primitive type.

tên là Đối tượng chuỗi để nó hoạt động. Nếu bạn muốn sắp xếp số cuộn của sinh viên hơn sử dụng mã dưới đây.

public int compareTo(Object obj1) { // For Comparable Interface
    Student s = (Student) obj1;
    return rollno - s.getRollno();
}  

hoặc là

public int compare(Object obj1,Object obj2) { // For Comparator interface
    Student s1 = (Student) obj1;
    Student s2 = (Student) obj2;
    return s1.getRollno() - s2.getRollno();
}  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.