โค้ดยิม/จาวาบล็อก/สุ่ม/คลาสตัวเปรียบเทียบของ Java
John Squirrels
ระดับ
San Francisco

คลาสตัวเปรียบเทียบของ Java

เผยแพร่ในกลุ่ม
สวัสดี! วันนี้เราจะพูดถึงการเปรียบเทียบวัตถุ คลาสตัวเปรียบเทียบของ Java - 1 อืม... แต่เราเคยพูดหัวข้อนี้มากกว่าหนึ่งครั้งไม่ใช่เหรอ? :/ เรารู้วิธี==การทำงานของตัวดำเนินการตลอดจนequals()วิธีhashCode()การ การเปรียบเทียบแตกต่างกันเล็กน้อย ก่อนหน้านี้ เรามักจะหมายถึง "การตรวจสอบวัตถุเพื่อความเท่าเทียมกัน" แต่เหตุผลในการเปรียบเทียบวัตถุกันอาจแตกต่างไปจากเดิมอย่างสิ้นเชิง! สิ่งที่ชัดเจนที่สุดคือการเรียงลำดับ ฉันคิดว่าถ้าคุณได้รับคำสั่งให้จัดเรียงArrayList<>ตัวเลขหรือสตริง คุณจะสามารถจัดการสิ่งนี้ได้โดยไม่มีปัญหา:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       String name1 = "Masha";
       String name2 = "Sasha";
       String name3 = "Dasha";

       List<String> names = new ArrayList<>();
       names.add(name1);
       names.add(name2);
       names.add(name3);

       Collections.sort(names);
       System.out.println(names);
   }
}
เอาต์พุตคอนโซล:
[Dasha, Masha, Sasha]
หากคุณจำCollectionsคลาสและsort()วิธีการของมันได้ ทำได้ดีมาก! ฉันคิดว่าคุณจะไม่มีปัญหากับตัวเลข นี่เป็นงานที่ท้าทายมากขึ้นสำหรับคุณ:
public class Car {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   // ...getters, setters, toString()

}

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);
   }
}
งานเป็นเรื่องง่ายจริงๆ เรามีCarวัตถุคลาสและ 3 รถยนต์ คุณช่วยเรียงลำดับรถในรายการได้ไหม? คุณอาจจะถามว่า "ควรจัดเรียงอย่างไร" โดยชื่อ? ตามปีที่ผลิต? ด้วยความเร็วสูงสุด? คำถามที่ยอดเยี่ยม ในขณะนี้ เราไม่ทราบวิธีการจัดเรียงCarวัตถุ และโดยธรรมชาติแล้ว Java ก็ไม่รู้เหมือนกัน! เมื่อเราพยายามส่งรายการCarวัตถุไปยังCollections.sort()เมธอด เราได้รับข้อผิดพลาด:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(20012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       // Compilation error!
       Collections.sort(cars);
   }
}
และภาษาจะรู้วิธีจัดเรียงวัตถุของชั้นเรียนที่คุณเขียนได้อย่างไร ขึ้นอยู่กับว่าโปรแกรมของคุณต้องการทำอะไร เราต้องสอน Java เพื่อเปรียบเทียบวัตถุเหล่านี้ และเพื่อเปรียบเทียบให้ตรงตามที่เราต้องการ Java มีกลไกพิเศษสำหรับสิ่งนี้: Comparableอินเทอร์เฟซ ในการเปรียบเทียบและจัดเรียงCarออบเจกต์ของเรา คลาสจะต้องใช้อินเทอร์เฟซนี้ซึ่งประกอบด้วยเมธอดเดียว: compareTo():
public class Car implements Comparable<Car> {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   @Override
   public int compareTo(Car o) {
       return 0;
   }

   // ...getters, setters, toString()

}
โปรดทราบที่เราระบุComparable<Car>อินเทอร์เฟซ ไม่ใช่แค่Comparable. นี่คืออินเทอร์เฟซที่กำหนดพารามิเตอร์ นั่นคือเราต้องระบุคลาสที่เกี่ยวข้องเฉพาะ โดยหลักการแล้ว คุณสามารถลบออก<Car>จากอินเทอร์เฟซได้ แต่การเปรียบเทียบจะยึดตามObjectวัตถุตามค่าเริ่มต้น แทนที่จะเป็นcompareTo(Car o)เมธอด คลาสของเราจะมี:
@Override
   public int compareTo(Object o) {
       return 0;
   }
แน่นอน มันง่ายกว่ามากสำหรับเราที่จะทำงานCarด้วย ภายในcompareTo()วิธีการ เราใช้ตรรกะของเราในการเปรียบเทียบรถยนต์ สมมติว่าเราต้องจัดเรียงตามปีที่ผลิต คุณอาจสังเกตเห็นว่าcompareTo()เมธอดส่งคืน an intไม่ใช่booleana อย่าปล่อยให้สิ่งนี้ทำให้คุณประหลาดใจ เมื่อเราเปรียบเทียบสองวัตถุ มีความเป็นไปได้ 3 ประการ:
  • а < b
  • a > b
  • a == b.
booleanมีค่าเพียง 2 ค่า: จริงและเท็จ ซึ่งใช้ไม่ได้ผลในการเปรียบเทียบวัตถุ ด้วยintทุกอย่างง่ายขึ้นมาก หากค่าที่ส่งกลับเป็น> 0ดังนั้น a > bถ้าผลลัพธ์ของcompareToคือ< 0แล้วa < b. และถ้าผลลัพธ์คือ== 0วัตถุสองชิ้นจะเท่ากันa == b: การสอนชั้นเรียนของเราให้จัดเรียงรถยนต์ตามปีที่ผลิตนั้นง่ายมาก:
@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
แต่เกิดอะไรขึ้นที่นี่? เรานำวัตถุรถยนต์หนึ่งชิ้น ( this) รับปีที่ผลิตของรถคันนี้ และลบด้วยปีที่ผลิตของรถยนต์อีกคันหนึ่ง หากปีที่ผลิตรถยนต์คันแรกมากกว่า วิธีนี้จะคืนค่าint > 0เป็น ซึ่ง หมายความว่าthis car >รถยนต์ oในทางกลับกัน หากปีที่ผลิตรถยนต์คันที่สอง ( о) มากกว่า วิธีการจะส่งกลับเป็นจำนวนลบ ซึ่งหมายความo > thisว่า สุดท้ายหากเท่ากัน วิธีการจะคืน0ค่า กลไกง่ายๆ นี้เพียงพอแล้วสำหรับเราในการจัดเรียงคอลเลกชันของCarวัตถุ! คุณไม่ต้องทำอะไรอีก ตรวจสอบออก:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       // There was previously an error here
       Collections.sort(cars);
       System.out.println(cars);
   }
}
เอาต์พุตคอนโซล:
[Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350},
Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290}]
รถเรียงตามที่เราต้องการ! :) คลาสตัวเปรียบเทียบของ Java - 2ฉันควรใช้เมื่อใดComparable? วิธีการเปรียบเทียบที่ใช้Comparableเรียกว่าลำดับตามธรรมชาติ นี่เป็นเพราะในcompareTo()วิธีการที่คุณกำหนดวิธีการเปรียบเทียบวัตถุของคลาสนี้โดยทั่วไปหรือเป็นธรรมชาติที่สุด Java มีลำดับตามธรรมชาติอยู่แล้ว ตัวอย่างเช่น Java รู้ว่าสตริงมักจะถูกจัดเรียงตามตัวอักษร และตัวเลขโดยการเพิ่มค่าตัวเลข ดังนั้น หากคุณเรียกsort()ใช้เมธอดในรายการของตัวเลขหรือสตริง พวกมันจะถูกจัดเรียง หากโปรแกรมของเรามักจะเปรียบเทียบและจัดเรียงรถยนต์ตามปีที่ผลิต เราควรกำหนดการจัดเรียงตามธรรมชาติสำหรับรถยนต์โดยใช้อินComparable<Car>เทอร์เฟซและcompareTo()วิธี. แต่ถ้ามันไม่เพียงพอสำหรับเราล่ะ ลองจินตนาการว่าโปรแกรมของเราไม่ง่ายนัก ในกรณีส่วนใหญ่ การจัดเรียงตามธรรมชาติของรถยนต์ (ซึ่งเรากำหนดให้ดำเนินการตามปีที่ผลิต) เหมาะสมกับเรา แต่บางครั้งลูกค้าของเราก็ชื่นชอบการขับรถเร็ว หากเรากำลังเตรียมแคตตาล็อกรถให้พวกเขาอ่าน ควรจัดเรียงรถด้วยความเร็วสูงสุด คลาสตัวเปรียบเทียบของ Java - 3ตัวอย่างเช่น สมมติว่าเราต้องการจัดเรียงเช่นนี้ 15% ของเวลา เห็นได้ชัดว่าไม่เพียงพอสำหรับเราที่จะตั้งค่าCarการจัดเรียงตามธรรมชาติของคลาสเป็นตามความเร็วแทนที่จะเป็นปีที่ผลิต แต่เราไม่สามารถเพิกเฉยต่อลูกค้า 15% ของเราได้ ดังนั้นสิ่งที่เราจะทำ? อินเทอร์เฟซอื่นมาช่วยเราที่นี่: Comparator. เช่นเดียวกับComparableมันเป็นอินเทอร์เฟซแบบกำหนดพารามิเตอร์ ความแตกต่างคืออะไร? Comparableทำให้วัตถุของเรา "เปรียบเทียบได้" และกำหนดลำดับการจัดเรียงที่เป็นธรรมชาติที่สุด นั่นคือลำดับการจัดเรียงที่จะใช้ในกรณีส่วนใหญ่ Comparatorเป็นอินเทอร์เฟซ "เปรียบเทียบ" ที่แยกต่างหาก หากเราจำเป็นต้องใช้ลำดับการจัดเรียงแบบพิเศษ เราไม่จำเป็นต้องเข้าไปในคลาสCarและเปลี่ยนตรรกะของcompareTo(). แต่เราสามารถสร้างคลาสแยกต่างหากที่ใช้ Comparator และสอนวิธีดำเนินการเรียงลำดับที่เราต้องการได้!
import java.util.Comparator;

public class MaxSpeedCarComparator implements Comparator<Car> {

   @Override
   public int compare(Car o1, Car o2) {
       return o1.getMaxSpeed() - o2.getMaxSpeed();
   }
}
อย่างที่คุณเห็น ของเราComparatorค่อนข้างเรียบง่าย เราจำเป็นต้องใช้วิธีอินเทอร์เฟซเดียวเท่านั้น: compare(). ใช้Carวัตถุสองชิ้นเป็นอินพุตและเปรียบเทียบความเร็วสูงสุดด้วยวิธีปกติ (โดยการลบ) เช่นเดียวกับcompareTo()จะส่งกลับ an intและหลักการเปรียบเทียบเหมือนกัน เราจะใช้สิ่งนี้อย่างไร ทุกอย่างตรงไปตรงมา:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       Comparator speedComparator = new MaxSpeedCarComparator();
       Collections.sort(cars, speedComparator);

       System.out.println(cars);
   }
}
เอาต์พุตคอนโซล:
[Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290},
Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350}]
เราเพียงแค่สร้างวัตถุเปรียบเทียบและส่งต่อไปยังCollections.sort()วิธีการพร้อมกับรายการที่จะจัดเรียง เมื่อsort()เมธอดได้รับตัวเปรียบเทียบ จะไม่ใช้การเรียงลำดับตามธรรมชาติที่กำหนดไว้ในเมธอดCarของคลาส compareTo()แต่จะใช้อัลกอริธึมการเรียงลำดับที่กำหนดโดยตัวเปรียบเทียบที่ส่งผ่านไปแทน ข้อดีของการทำเช่นนี้คืออะไร? ประการแรก ความเข้ากันได้กับรหัสที่มีอยู่ เราได้สร้างวิธีการคัดแยกแบบพิเศษขึ้นมาใหม่ โดยยังคงรักษาวิธีการคัดแยกที่มีอยู่ซึ่งจะใช้เวลาส่วนใหญ่ไว้ เราไม่ได้แตะCarชั้นเรียนเลย มันเป็นComparableและมันก็ยังคงอยู่:
public class Car implements Comparable<Car> {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   @Override
   public int compareTo(Car o) {
       return this.getManufactureYear() - o.getManufactureYear();
   }

   // ...getters, setters, toString()

}
ประการที่สองความยืดหยุ่น เราสามารถเพิ่มอัลกอริทึมการเรียงลำดับได้มากเท่าที่เราต้องการ ตัวอย่างเช่น เราสามารถจัดเรียงรถตามสี ความเร็ว น้ำหนัก หรือจำนวนครั้งที่รถถูกใช้ในภาพยนตร์แบทแมน สิ่งที่เราต้องทำคือสร้างเพิ่มเติมComparator. แค่นั้นแหละ! วันนี้ คุณได้ศึกษากลไกสำคัญสองอย่างที่คุณมักจะใช้ในโครงการจริงในที่ทำงาน แต่อย่างที่คุณทราบ ทฤษฎีที่ปราศจากการปฏิบัติก็ไร้ความหมาย ถึงเวลารวบรวมความรู้ของคุณและทำภารกิจให้สำเร็จ!
ความคิดเห็น
  • เป็นที่นิยม
  • ใหม่
  • เก่า
คุณต้องลงชื่อเข้าใช้เพื่อแสดงความคิดเห็น
หน้านี้ยังไม่มีความคิดเห็นใด ๆ