เครื่องเปรียบเทียบ การเรียงลำดับคอลเลกชัน - 1

“สวัสดี อามีโก้!”

"สวัสดี บิลาโบ!"

"วันนี้เราจะตรวจสอบหัวข้อเล็กๆ แต่น่าสนใจและมีประโยชน์: การเรียงลำดับคอลเลกชัน"

"การเรียงลำดับ? ฉันได้ยินบางอย่างเกี่ยวกับเรื่องนั้น"

"นานมาแล้ว โปรแกรมเมอร์ทุกคนต้องสามารถเขียน sorting algorithm ได้ ทำได้และต้องเขียนมัน แต่วันเวลาเหล่านั้นจบลงแล้ว ทุกวันนี้ การเขียน sorting code ของคุณเองถือเป็นรูปแบบที่ไม่ดี ถูกประดิษฐ์ขึ้น"

"ใน Java (และภาษาโปรแกรมอื่นๆ) การเรียงลำดับได้ถูกนำมาใช้แล้ว  งานของคุณคือเรียนรู้วิธีการใช้สิ่งที่มีอยู่แล้วอย่างเหมาะสม "

"ตกลง."

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

“ใช่ ฉันจำได้ ฉันใช้วิธีนี้ครั้งนึงในการจัดเรียงรายการตัวเลข”

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

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

"ให้ฉันแสดงตัวอย่างให้คุณเห็นก่อน จากนั้นทุกอย่างจะชัดเจนขึ้น:"

ตัวอย่าง
public class Woman implements Comparable<Woman>
{
public int age;

public Woman(int age) {
this.age = age;
}

public int compareTo(Woman o)
{
return this.age - o.age;
}
}
ตัวอย่างของวิธีการใช้:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Collections.sort(women);
}

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

"และการเปรียบเทียบทำงานอย่างไร ฉันคาดหวังว่ามันจะคืนค่าจริงหรือเท็จขึ้นอยู่กับว่าวัตถุที่ส่งผ่านนั้นมีค่ามากกว่าหรือเล็กกว่า"

"สิ่งต่าง ๆ มีความซับซ้อนมากขึ้นที่นี่ วิธีการเปรียบเทียบเพื่อไม่คืนค่าจริง/เท็จ แต่จะส่งคืนค่า int ซึ่งจริง ๆ แล้วทำเพื่อความเรียบง่าย

"เมื่อคอมพิวเตอร์ต้องการตรวจสอบว่าตัวเลขหนึ่งมากกว่าอีกจำนวนหนึ่งหรือไม่ คอมพิวเตอร์ก็แค่ลบตัวเลขที่สองออกจากตัวเลขแรก แล้วดูที่ผลลัพธ์ หากผลลัพธ์เป็น 0 แสดงว่าตัวเลขนั้นเท่ากัน หากผลลัพธ์น้อยกว่าศูนย์ แล้วจำนวนที่สองจะมากกว่า และถ้าผลลัพธ์มากกว่าศูนย์ ตัวเลขแรกก็จะมากกว่า"

"ใช้ตรรกะเดียวกันนี้ ตามข้อมูลจำเพาะ วิธีการเปรียบเทียบต้องคืนค่าศูนย์หากวัตถุที่เปรียบเทียบมีค่าเท่ากัน หากวิธีการเปรียบเทียบส่งกลับตัวเลขที่มากกว่าศูนย์ แสดงว่าวัตถุของเรามีค่ามากกว่าวัตถุที่ส่งผ่าน "หากการเปรียบเทียบถึง เมธอดส่งคืนตัวเลขที่น้อยกว่าศูนย์ จากนั้น 'ค่านี้' จะน้อยกว่าวัตถุที่ส่งผ่าน"

"นั่นเป็นเรื่องที่แปลกเล็กน้อย"

"ใช่ แต่ถ้าคุณกำลังเปรียบเทียบออบเจกต์โดยอิงจากคุณสมบัติตัวเลขบางอย่าง คุณก็สามารถคืนค่าผลต่างระหว่างออบเจกต์เหล่านั้นได้โดยการลบสิ่งหนึ่งออกจากอีกสิ่งหนึ่ง เหมือนกับที่ทำในตัวอย่างด้านบน"

public int compareTo(Woman o)
{
return this.age - o.age;
}

"ฉันคิดว่าฉันเข้าใจทุกอย่าง แต่อาจจะไม่ แต่เกือบทุกอย่าง"

"เยี่ยมมาก ตอนนี้เรามาพิจารณาปัญหาเชิงปฏิบัติกันดีกว่า สมมติว่าคุณเขียนเว็บไซต์เจ๋งๆ สำหรับทำเสื้อผ้าผู้หญิงในประเทศจีน คุณใช้คลาส Woman เพื่ออธิบายลูกค้าของคุณ คุณสร้างหน้าเว็บที่มีตารางที่คุณสามารถดูได้ทั้งหมด . แต่มีปัญหา… "

"วัตถุ Woman ของคุณไม่เพียงแต่ประกอบด้วยอายุเท่านั้น แต่ยังมีข้อมูลอื่นๆ อีกจำนวนมาก เช่น ชื่อ นามสกุล ส่วนสูง น้ำหนัก จำนวนลูก และอื่นๆ"

"ตารางผู้ใช้มีหลายคอลัมน์ และนี่คือคำถาม: คุณจะจัดเรียงผู้ใช้ของคุณตามเกณฑ์ต่างๆ ได้อย่างไร ตามน้ำหนัก ตามอายุ ตามนามสกุล"

"อืม ใช่ ฉันมักจะเห็นตารางที่ให้คุณจัดเรียงตามคอลัมน์ แล้วคุณจะทำอย่างไร"

"สำหรับสิ่งนี้ เรามีอินเทอร์เฟซที่สองที่ฉันอยากจะบอกคุณเกี่ยวกับวันนี้: อินเทอร์เฟซตัวเปรียบเทียบ นอกจากนี้ยังมีวิธีการเปรียบเทียบ แต่ต้องใช้สองอาร์กิวเมนต์ ไม่ใช่หนึ่ง: int เปรียบเทียบ (T o1, T o2) นี่คือวิธีการ ผลงาน:"

ตัวอย่าง
public class Woman
{
public int age;
public int childrenCount;
public int weight;
public int height;
public String name;

public Woman(int age) {
this.age = age;
}
}
ตัวอย่างของวิธีการใช้:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Comparator<Woman> compareByHeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.height - o2.height;
}
};

Collections.sort(women, compareByHeight);
}

"อินเทอร์เฟซ Comparator ไม่ได้ซ่อนตรรกะการเปรียบเทียบวัตถุภายในคลาสของวัตถุที่กำลังเปรียบเทียบ แต่จะนำไปใช้ในคลาสที่แยกต่างหากแทน"

"ดังนั้น ฉันสามารถสร้างคลาสหลายคลาสที่ใช้อินเทอร์เฟซ Comparator และให้แต่ละคลาสเปรียบเทียบคุณสมบัติที่แตกต่างกัน น้ำหนักเป็นหนึ่ง อายุเป็นอีกส่วน และส่วนสูงเป็นสาม"

"ใช่ มันง่ายและสะดวกมาก"

"เราเรียก เมธอด Collections.sortโดยส่งรายการของวัตถุและวัตถุพิเศษอื่นเป็นอาร์กิวเมนต์ที่สอง ซึ่งใช้อิน เทอร์เฟซ Comparatorและบอกวิธีเปรียบเทียบคู่ของวัตถุอย่างถูกต้องในกระบวนการเรียงลำดับ"

"อืม ฉันคิดว่าฉันเข้าใจทุกอย่างแล้ว ขอฉันลองดูก่อน สมมติว่าฉันต้องจัดเรียงผู้ใช้ตามน้ำหนัก มันก็จะประมาณนี้:"

ตัวอย่างการจัดเรียงผู้ใช้ตามน้ำหนัก:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

"ใช่แน่นอน"

"เยี่ยมมาก แต่ถ้าฉันต้องการเรียงลำดับกลับกันล่ะ"

"ลองคิดดูสิ คำตอบนั้นง่ายมาก!"

"เข้าใจแล้ว! แบบนี้:"

เรียงลำดับจากน้อยไปหามาก:
return o1.weight - o2.weight;
เรียงลำดับจากมากไปน้อย:
return o2.weight – o1.weight;

"ถูกต้อง ทำได้ดีมาก"

"และถ้าฉันต้องการจัดเรียงตามนามสกุล ฉันจะจัดเรียงสตริงได้อย่างไร Bilaabo"

"คลาส String ใช้เมธอดของ expandTo แล้ว คุณเพียงแค่เรียกมันว่า:"

ตัวอย่างการจัดเรียงผู้ใช้ตามชื่อ:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

"นั่นเป็นบทเรียนที่ดี บิลาโบ ขอบคุณมาก"

"และขอบคุณคุณเพื่อนของฉัน!"