ความแตกต่างระหว่าง Compare () และ CompareTo () คืออะไร?


110

อะไรคือความแตกต่างระหว่าง Java compare()และcompareTo()วิธีการ? วิธีการเหล่านั้นให้คำตอบเหมือนกันหรือไม่?


1
คุณหมายถึงการเปรียบเทียบ Class Methode ใด
Markus Lausberg

สำหรับคำอธิบายโดยละเอียดของการใช้งานทั้งCompare
mel3kings

คำตอบ:


160

จากJavaNotes :

  • a.compareTo(b):
    อินเทอร์เฟซที่เปรียบเทียบได้:เปรียบเทียบค่าและส่งกลับค่า int ซึ่งจะบอกว่าค่าเปรียบเทียบน้อยกว่าเท่ากับหรือมากกว่า
    ถ้าคลาสออบเจ็กต์ของคุณมีลำดับตามธรรมชาติให้ใช้Comparable<T>อินเทอร์เฟซและกำหนดวิธีการนี้ ทุกชั้นเรียน Java ที่มีการสั่งซื้อจากธรรมชาติใช้Comparable<T>- ตัวอย่าง: String, เรียนเสื้อคลุม ,BigInteger

  • compare(a, b):
    อินเตอร์เฟสตัว เปรียบเทียบ:เปรียบเทียบค่าของสองวัตถุ นี้จะดำเนินการเป็นส่วนหนึ่งของComparator<T>อินเตอร์เฟซและการใช้งานทั่วไปคือการกำหนดหนึ่งหรือขนาดเล็กมากขึ้นอาคารเรียนที่ใช้นี้จะส่งผ่านไปยังวิธีการเช่นsort()หรือสำหรับการใช้งานโดยการจัดเรียงโครงสร้างข้อมูลเช่นTreeMapTreeSetและ คุณอาจต้องการสร้างวัตถุตัวเปรียบเทียบสำหรับสิ่งต่อไปนี้:

    • การเปรียบเทียบหลายรายการ เพื่อจัดหาวิธีต่างๆในการจัดเรียงบางสิ่ง ตัวอย่างเช่นคุณอาจต้องการจัดเรียงคลาส Person ตามชื่อ, ID, อายุ, ส่วนสูง, ... คุณจะต้องกำหนดตัวเปรียบเทียบสำหรับแต่ละรายการเพื่อส่งต่อไปยังsort()เมธอด
    • คลาสระบบเพื่อจัดเตรียมวิธีการเปรียบเทียบสำหรับคลาสที่คุณไม่สามารถควบคุมได้ ตัวอย่างเช่นคุณสามารถกำหนดตัวเปรียบเทียบสำหรับสตริงที่เปรียบเทียบตามความยาว
    • รูปแบบกลยุทธ์ในการใช้รูปแบบกลยุทธ์ซึ่งเป็นสถานการณ์ที่คุณต้องการแสดงอัลกอริทึมเป็นวัตถุที่คุณสามารถส่งผ่านเป็นพารามิเตอร์บันทึกในโครงสร้างข้อมูล ฯลฯ

หากคลาสของคุณมีลำดับการเรียงลำดับตามธรรมชาติคุณอาจไม่จำเป็นต้องเปรียบเทียบ ()


สรุปจากhttp://www.digizol.com/2008/07/java-sorting-comparator-vs-comparable.html

เทียบเคียง
วัตถุเปรียบได้มีความสามารถในการเปรียบเทียบตัวเองกับวัตถุอื่น

เปรียบเทียบ
วัตถุเปรียบเทียบความสามารถในการเปรียบเทียบสองวัตถุที่แตกต่าง คลาสไม่ได้เปรียบเทียบอินสแตนซ์ แต่เป็นอินสแตนซ์ของคลาสอื่น


ใช้บริบทกรณี:

อินเทอร์เฟซที่เทียบเคียงได้

เท่ากับวิธีการและ==และ!= ผู้ประกอบการทดสอบเพื่อความเท่าเทียมกัน / ความไม่เท่าเทียมกัน แต่ไม่ได้ให้วิธีการทดสอบเพื่อหาค่าญาติ
บางคลาส (เช่นสตริงและคลาสอื่น ๆ ที่มีการเรียงลำดับตามธรรมชาติ) ใช้Comparable<T>อินเทอร์เฟซซึ่งกำหนดcompareTo()วิธีการ
คุณจะต้องนำไปใช้Comparable<T>ในชั้นเรียนของคุณหากคุณต้องการใช้ด้วยCollections.sort()หรือArrays.sort()วิธีการ

การกำหนดวัตถุตัวเปรียบเทียบ

คุณสามารถสร้างเทียบการจัดเรียงวิธีการใด ๆ โดยพลสำหรับการเรียนใด
ยกตัวอย่างเช่นStringระดับกำหนดเปรียบเทียบCASE_INSENSITIVE_ORDER


ความแตกต่างระหว่างสองแนวทางสามารถเชื่อมโยงกับแนวคิดของ:
คอลเลกชันที่สั่งซื้อ :

เมื่อมีการสั่งซื้อคอลเลคชันหมายความว่าคุณสามารถทำซ้ำในคอลเลกชั่นตามลำดับที่เจาะจง (ไม่สุ่ม) ( Hashtableไม่ได้เรียงลำดับ a )

คอลเลกชันที่มีธรรมชาติไม่ได้รับคำสั่งเพียง แต่เรียง การกำหนดลำดับตามธรรมชาติอาจเป็นเรื่องยาก! ( ตามลำดับสตริงธรรมชาติ )


ความแตกต่างอีกประการหนึ่งที่HaveAGuessชี้ให้เห็นในความคิดเห็น :

  • Comparable อยู่ในการนำไปใช้งานและมองไม่เห็นจากอินเทอร์เฟซดังนั้นเมื่อคุณจัดเรียงคุณไม่รู้จริงๆว่าจะเกิดอะไรขึ้น
  • Comparator ช่วยให้คุณมั่นใจได้ว่าการสั่งซื้อจะถูกกำหนดไว้อย่างดี

2
เนื่องจากคำตอบนี้เป็นคำตอบที่ละเอียดถี่ถ้วนนี่คือสิ่งที่ทำให้ฉันรำคาญเกี่ยวกับการเปรียบเทียบที่คุณอาจต้องการเพิ่ม: มันอยู่ในการนำไปใช้งานและมองไม่เห็นจากอินเทอร์เฟซดังนั้นเมื่อคุณเรียงลำดับคุณจะไม่รู้จริงๆว่าจะเกิดอะไรขึ้น การใช้เครื่องเปรียบเทียบช่วยให้คุณมั่นใจได้ว่าการสั่งซื้อจะได้รับการกำหนดไว้อย่างดี
HaveAGuess

@HaveAGuess จุดดี ฉันได้รวมความคิดเห็นของคุณไว้ในคำตอบเพื่อให้มองเห็นได้มากขึ้น
VonC

วัตถุมีลำดับตามธรรมชาติคำสั่งตามธรรมชาติหมายถึงอะไรที่นี่? สมาชิกข้อมูลสตริงสำหรับชื่อเช่นในคลาสพนักงานมีลำดับตามธรรมชาติหรือไม่?
Narendra Jaggi

@NarendraJaggi ดูen.wikipedia.org/wiki/Enumeration คำสั่งที่อำนวยความสะดวกในการแจงนับ "เป็นธรรมชาติ" ในแง่ที่ว่าการจัดลำดับที่ดีในชุดดัชนีเป็นวิธีที่ไม่ซ้ำใครในการแสดงรายการองค์ประกอบถัดไปโดยมีการแจงนับบางส่วน
VonC

2
@VedantKekan ขอบคุณครับ ฉันได้กู้คืน 2 ลิงก์ในคำตอบนี้
VonC

16

compareTo()มาจากComparableอินเทอร์เฟซ

compare()มาจากComparatorอินเทอร์เฟซ

ทั้งสองวิธีทำสิ่งเดียวกัน แต่แต่ละอินเทอร์เฟซจะใช้ในบริบทที่แตกต่างกันเล็กน้อย

เทียบเคียงกับอินเตอร์เฟซที่จะใช้ในการกำหนดสั่งซื้อธรรมชาติบนวัตถุของชั้นการดำเนินการ compareTo()วิธีการที่เรียกว่าวิธีการเปรียบเทียบธรรมชาติ เปรียบเทียบอินเตอร์เฟซที่จะใช้ในการกำหนดสั่งซื้อรวมกับวัตถุของชั้นการดำเนินการ สำหรับข้อมูลเพิ่มเติมโปรดดูลิงก์ว่าควรใช้อินเทอร์เฟซแต่ละรายการเมื่อใด


ช่วยยกตัวอย่างได้ไหมทั้งสองวิธีให้คำตอบเหมือนกัน?

ฉันไม่รู้ว่าทำไม 'เปรียบเทียบได้' จึงเป็นแบบธรรมชาติ? เราแต่งเองไม่ได้หรอ
c-an

14

ความคล้ายคลึงกัน:
ทั้งสองแบบเป็นวิธีที่กำหนดเองในการเปรียบเทียบวัตถุสองชิ้น
ทั้งสองส่งคืนการintอธิบายความสัมพันธ์ระหว่างวัตถุสองชิ้น

ความแตกต่าง: วิธีcompare()นี้เป็นวิธีการที่คุณจำเป็นต้องใช้หากคุณใช้Comparatorอินเทอร์เฟซ ช่วยให้คุณสามารถส่งผ่านวัตถุสองชิ้นไปยังเมธอดและส่งกลับคำintอธิบายความสัมพันธ์ของพวกเขา

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

เมธอดcompareTo()นี้เป็นวิธีการที่คุณจำเป็นต้องใช้หากคุณใช้Comparableอินเทอร์เฟซ ช่วยให้สามารถเปรียบเทียบวัตถุกับวัตถุประเภทเดียวกันได้

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

สรุป:
โดยทั่วไปเป็นสองวิธีที่แตกต่างกันในการเปรียบเทียบสิ่งต่างๆ


9

วิธีการไม่จำเป็นต้องให้คำตอบเดียวกัน ขึ้นอยู่กับวัตถุ / คลาสที่คุณเรียกใช้

หากคุณกำลังใช้คลาสของคุณเองซึ่งคุณรู้ว่าคุณต้องการเปรียบเทียบในบางขั้นตอนคุณอาจให้พวกเขาใช้อินเทอร์เฟซเปรียบเทียบและใช้เมธอด CompareTo () ตามนั้น

หากคุณกำลังใช้คลาสบางคลาสจาก API ที่ไม่ได้ใช้อินเทอร์เฟซที่เปรียบเทียบได้ แต่คุณยังต้องการเปรียบเทียบ ได้แก่ สำหรับการเรียงลำดับ. คุณสามารถสร้างคลาสของคุณเองซึ่งใช้อินเทอร์เฟซตัวเปรียบเทียบและในวิธีการเปรียบเทียบ () ที่คุณใช้ตรรกะ


3

อินเทอร์เฟซที่เปรียบเทียบได้มีวิธีการที่เรียกว่าcompareTo(obj)ซึ่งใช้อาร์กิวเมนต์เดียวเท่านั้นและจะเปรียบเทียบตัวเองกับอินสแตนซ์หรืออ็อบเจ็กต์อื่นในคลาสเดียวกัน

อินเทอร์เฟซตัวเปรียบเทียบมีวิธีการที่เรียกว่าcompare(obj1,obj2)ซึ่งรับสองอาร์กิวเมนต์และจะเปรียบเทียบค่าของวัตถุสองชิ้นจากคลาสเดียวกันหรือต่างกัน


3
compareTo(T object)

มาจากอินเทอร์เฟซ java.lang.Comparable นำไปใช้เพื่อเปรียบเทียบอ็อบเจ็กต์นี้กับอ็อบเจ็กต์อื่นเพื่อให้ค่า int เชิงลบสำหรับอ็อบเจ็กต์นี้มีค่าน้อยกว่า, 0 สำหรับเท่ากับหรือค่าบวกสำหรับค่าที่มากกว่าอีก นี่เป็นวิธีการเปรียบเทียบที่สะดวกกว่า แต่ต้องนำไปใช้ในทุกคลาสที่คุณต้องการเปรียบเทียบ

compare(T obj1, T obj2)

มาจากอินเทอร์เฟซ java.util.Comparator ซึ่งใช้งานในคลาสแยกต่างหากที่เปรียบเทียบอ็อบเจ็กต์ของคลาสอื่นเพื่อให้ค่า int เชิงลบสำหรับอ็อบเจ็กต์แรกที่มีค่าน้อยกว่า 0 สำหรับค่าเท่ากับหรือค่าบวกสำหรับอ็อบเจ็กต์ที่สอง จำเป็นเมื่อคุณไม่สามารถสร้างคลาสใช้ CompareTo () ได้เนื่องจากไม่สามารถแก้ไขได้ นอกจากนี้ยังใช้เมื่อคุณต้องการวิธีต่างๆในการเปรียบเทียบวัตถุไม่ใช่เพียงวิธีเดียว (เช่นตามชื่อหรืออายุ)


3

ใช้เปรียบเทียบเราสามารถมีจำนวน n ตรรกะการเปรียบเทียบที่เขียนขึ้นสำหรับชั้นเรียน

เช่น

สำหรับคลาสรถยนต์

เราสามารถมีคลาส Comparator เพื่อเปรียบเทียบตามหมายเลขรุ่นรถ นอกจากนี้เรายังสามารถมีคลาส Comparator เพื่อเปรียบเทียบตามรุ่นปีของรถ

คลาสรถยนต์

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

}

ตัวเปรียบเทียบ # 1 ตามหมายเลขรุ่น

public class CarModelNoCompartor implements Comparator<Car>{

    public int compare(Car o1, Car o2) {

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

}

ตัวเปรียบเทียบ # 2 ตามรุ่นปี

public class CarModelYearComparator implements Comparator<Car> {

    public int compare(Car o1, Car o2) {

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

}

แต่นี่เป็นไปไม่ได้กับกรณีของอินเทอร์เฟซที่เปรียบเทียบได้

ในกรณีของอินเตอร์เฟซเทียบเคียงเราสามารถมีเพียงหนึ่งในตรรกะ compareTo () วิธีการ


2

ความสัมพันธ์ของวัตถุที่มีวิธีการนี้และผู้ทำงานร่วมกันแตกต่างกัน

compareTo()เป็นวิธีการของอินเทอร์เฟซที่เปรียบเทียบได้ดังนั้นจึงใช้เพื่อเปรียบเทียบอินสแตนซ์นี้กับอินสแตนซ์อื่น

compare()เป็นวิธีการหนึ่งของตัวเปรียบเทียบอินเทอร์เฟซดังนั้นจึงใช้เพื่อเปรียบเทียบสองอินสแตนซ์ที่แตกต่างกันของคลาสอื่นซึ่งกันและกัน

หากคุณต้องการการนำไปใช้Comparableหมายความว่าสามารถเปรียบเทียบอินสแตนซ์ของคลาสได้อย่างง่ายดาย วิธี
การใช้งานComparatorอินสแตนซ์นั้นเหมาะที่จะเปรียบเทียบวัตถุที่แตกต่างกัน (ของคลาสอื่น ๆ )


2

ความแตกต่างหลักคือการใช้อินเทอร์เฟซ:

การเปรียบเทียบ (ซึ่งมี CompareTo ()) ต้องใช้วัตถุที่จะเปรียบเทียบ (เพื่อใช้ TreeMap หรือจัดเรียงรายการ) เพื่อใช้งานอินเทอร์เฟซนั้น แต่จะเกิดอะไรขึ้นถ้าชั้นเรียนไม่ใช้การเปรียบเทียบและคุณไม่สามารถเปลี่ยนแปลงได้เนื่องจากเป็นส่วนหนึ่งของไลบรารีของบุคคลที่สาม จากนั้นคุณต้องใช้ตัวเปรียบเทียบซึ่งสะดวกในการใช้งานเล็กน้อย


2

compareTo()ถูกเรียกบนวัตถุหนึ่งเพื่อเปรียบเทียบกับวัตถุอื่น compare()ถูกเรียกบนวัตถุบางอย่างเพื่อเปรียบเทียบวัตถุอื่นอีกสองชิ้น

ความแตกต่างอยู่ที่ตรรกะที่ทำการเปรียบเทียบจริงถูกกำหนดไว้


ไม่ใช่สิ่งที่ฉันเรียกว่าคำตอบที่ยอดเยี่ยม แต่ฉันไม่คิดว่ามันสมควรได้รับการโหวตลดลง
Paul Tomblin

ตกลงโดยส่วนตัวแล้วฉันขอสงวนการลงคะแนนสำหรับคำตอบที่ผิดหรือทำให้เข้าใจผิด อันนี้ถูกต้องแน่นอน
Joachim Sauer

แล้วคนที่ 'เป็นมิตร' ที่โหวตให้ฉันอยู่ที่ไหน? นี่เป็นคำตอบที่ถูกที่สองของฉันที่ถูกลดคะแนนเนื่องจากมีคนพลาดประเด็นนี้ ไม่ว่าจะเป็นจุดลงคะแนนหรือประเด็นของคำตอบของฉัน ชีวิตช่างโหดร้าย .. ;-)
Abgan

0

เมื่อคุณต้องการเรียงลำดับรายการที่มี Object Foo คลาส Foo จะต้องใช้อินเทอร์เฟซที่เทียบเคียงกันได้เนื่องจากการจัดเรียงเมทโธดของรายการใช้วิธีนี้

เมื่อคุณต้องการเขียนคลาส Util ซึ่งเปรียบเทียบสองคลาสอื่นคุณสามารถใช้คลาส Comparator ได้


0


ชื่อตารางพนักงาน, DoB, Salary
Tomas, 2/10/1982, 300
Daniel, 3/11/1990, 400
Kwame, 2/10/1998, 520

เทียบเคียงกับอินเตอร์เฟซที่ช่วยให้คุณสามารถเรียงลำดับรายชื่อของวัตถุเช่นพนักงานที่มีการอ้างอิงถึงข้อมูลหลักหนึ่ง - ตัวอย่างเช่นคุณสามารถจัดเรียงตามชื่อหรือตามเงินเดือนกับCompareTo ()วิธีการ

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

อินเทอร์เฟซที่ยืดหยุ่นมากขึ้นสำหรับข้อกำหนดดังกล่าวมีให้โดยอินเทอร์เฟซComparatorซึ่งมีวิธีเดียวคือการเปรียบเทียบ ()

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

โค้ดตัวอย่าง

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

อีกหนึ่งประเด็น:

  • compareTo()มาจากComparableอินเทอร์เฟซและcompare()มาจากComparatorอินเทอร์เฟซ
  • Comparableใช้เพื่อกำหนดลำดับเริ่มต้นสำหรับอ็อบเจ็กต์ภายในคลาสในขณะที่Comparatorใช้เพื่อกำหนดลำดับแบบกำหนดเองที่จะส่งผ่านไปยังเมธอด

0

มีด้านเทคนิคที่ควรให้ความสำคัญเช่นกัน สมมติว่าคุณต้องการการกำหนดพารามิเตอร์พฤติกรรมเปรียบเทียบจากคลาสไคลเอนต์และคุณสงสัยว่าจะใช้ComparableหรือComparatorสำหรับวิธีการเช่นนี้:

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

comparableจะเป็นแลมด้าหรือสิ่งของและไม่มีทางcomparableเข้าถึงฟิลด์ของthisโปเกมอนได้ (ในแลมบ์ดาthisหมายถึงอินสแตนซ์คลาสนอกในขอบเขตของแลมบ์ดาตามที่กำหนดไว้ในข้อความโปรแกรม) สิ่งนี้จึงไม่บินและเราต้องใช้ a Comparatorกับสองอาร์กิวเมนต์


0

ใช้อินเทอร์เฟซที่เปรียบเทียบได้สำหรับการจัดเรียงตามค่ามากกว่าหนึ่งค่าเช่นอายุชื่อ dept_name ... สำหรับค่าเดียวให้ใช้อินเตอร์เฟสตัวเปรียบเทียบ


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

ในที่นี้return obj1.compareTo(obj1)หรือใช้return obj1.compareTo(obj)คำสั่ง Object เท่านั้น ไม่อนุญาตให้ใช้แบบดั้งเดิม ตัวอย่างเช่น

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

แต่

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

ชื่อคือ String Object เพื่อให้มันใช้งานได้ หากคุณต้องการเรียงลำดับจำนวนนักเรียนมากกว่าใช้รหัสด้านล่าง

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

หรือ

public int compare(Object obj1,Object obj2) { // For Comparator interface
    Student s1 = (Student) obj1;
    Student s2 = (Student) obj2;
    return s1.getRollno() - s2.getRollno();
}  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.