JavaRush /Java блогу /Random-KY /Java тилиндеги компаратор

Java тилиндеги компаратор

Группада жарыяланган
Салам! Бүгүн биз an objectтерди салыштыруу жөнүндө сүйлөшөбүз. Ммм... Бирок биз бул тууралуу бир нече жолу сүйлөштүк окшойт? :/ Биз “ ==” операторунун кантип иштээрин, ошондой эле equals()жана ыкмаларын билебиз hashCode(). Салыштыруу бул жөнүндө эмес. Мурда биз "an objectтерди теңчorкке сынап көрүү" дегенди айтканбыз. Java тorндеги компаратор - 1Бирок an objectтерди бири-бири менен салыштыруу такыр башка максаттарга ээ болушу мүмкүн! Эң айкын нерсе сорттоо. Менин оюмча, эгер сизге сандардын же саптардын тизмесин иреттөө сунушталса 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 = "Даша";

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

       Collections.sort(names);
       System.out.println(names);
   }
}
Консолдук чыгаруу:

[Даша, Маша, Саша]
Классты 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;
   }

   //...геттеры, сеттеры, 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 an objectиси. Тизмедеги унааларды иргегенге абдан боорукер болуңуз! Балким, сиз: "Аларды кантип сорттоо керек?" Аты боюнча, чыгарылган жылы боюнча, максималдуу ылдамдык боюнча? Улуу суроо. Учурда класстын an objectтерин кантип сорттоо керектигин билбейбиз Car. Жана, албетте, Java да муну билбейт! Collections.sort()Объекттердин тизмесин методго өткөрүүгө аракет кылганда 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(20012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

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

       //ошибка компилятора!
       Collections.sort(cars);
   }
}
Чынында эле, тил сиз жазган an objectилерди кантип сорттоо керектигин кайдан билет? Бул сиздин программаңыздын максаттарына жараша болот. Биз кандайдыр бир жол менен Java тorн бул an objectтерди салыштырууга үйрөтүшүбүз керек. Жана бизге керектүү жолду салыштырыңыз. Бул үчүн Java атайын куралы бар - интерфейс Comparable. Англисче бул "салыштыруу" деп которулат. CarБиздин an objectилер бири-бири менен салыштырылышы жана кандайдыр бир жол менен сорттолушу үчүн класс бул интерфейсти ишке ашырып, өзүнүн жалгыз ыкмасын ишке ашырышы керек: 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;
   }

   //...геттеры, сеттеры, toString()

}
Көңүл буруу:Comparable<Car>Биз жөн гана эмес, интерфейсти аныктадык Comparable. Бул терилген интерфейс, башкача айтканда, ал байланышкан конкреттүү классты көрсөтүүнү талап кылат. Негизи, <Car>сиз аны интерфейстен алып салсаңыз болот, бирок андан кийин демейки боюнча an objectтерди салыштырат Object. Биздин класстагы методдун ордуна compareTo(Car o)бизде:
@Override
   public int compareTo(Object o) {
       return 0;
   }
Албетте, биз менен иштөө бир топ жеңил Car. Методдун ичинде compareTo()биз машиналарды салыштыруу логикасын ишке ашырабыз. Аларды чыгарылган жылы боюнча сорттоо керек дейли. Метод эмес, compareTo()маанини кайтарарын байкаган чыгарсыз . Бул сени таң калтырбасын. Чынында, эки an objectти салыштыруу бизге 3 мүмкүн болгон варианттарды берет: intboolean
  • а < b
  • a > b
  • a == b.
Анын boolean2 гана мааниси бар - чыныгы жана жалган, бул an objectтерди салыштыруу үчүн ыңгайсыз. Баары алда intканча жөнөкөй. Кайтаруу мааниси болсо > 0, анда a > b. Натыйжа болсо compareTo < 0, анда а < b. Ооба, эгерде натыйжа болсо == 0, анда эки an object бирдей болот: a == b. Биздин класска машиналарды чыгарылган жылы боюнча сорттоого үйрөтүү алмурутту аткылоо сыяктуу оңой:
@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
Бул жакта эмне болуп жатат? Биз бир автомобиль an objectисин ( this), бул машинанын чыгарылган жылын алып, андан башка машинанын (an objectти салыштырган) чыгарылган жылын алып салабыз. Биринчи машинанын чыгарылган жылы чоңураак болсо, ыкма кайра келет int > 0. Бул машине дегенди this >билдирет о. Эгерде, тескерисинче, экинчи машинанын чыгарылган жылы ( о) көбүрөөк болсо, анда ыкма терс санды кайтарат, демек о > this. Ооба, эгерде алар бирдей болсо, ыкма кайтып келет 0. Мындай жөнөкөй механизм an objectтердин коллекцияларын сорттоо үчүн жетиштүү 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);

       //тут раньше была ошибка
       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 тorндеги компаратор - 2Кандай учурларда колдонуш керек Comparable? Ишке ашырылган салыштыруу ыкмасы Comparable"табигый тартип" деп аталат. Себеби бул методдо compareTo()сиз программаңызда ушул класстын an objectилери үчүн колдонула турган эң кеңири таралган салыштыруу ыкмасын сүрөттөп бересиз. Табигый тартип Javaда мурунтан эле бар. Мисалы, Java саптар көбүнчө алфавиттик тартипте, ал эми сандар көбүнчө өсүү боюнча иреттелерин билет. Ошондуктан, эгер сиз ыкманы сандар же саптар тизмесинде чакырсаңыз sort(), алар иргелет. Comparable<Car>Эгерде биздин программада автомобилдер көпчүлүк учурда чыгарылган жылы боюнча салыштырылып, сорттолсо, анда интерфейс жана ыкманы колдонуу менен алар үчүн табигый сортту аныктоо зарыл compareTo(). Бирок бул бизге жетишсиз болсочу? Биздин программа анчалык жөнөкөй эмес экенин элестетип көрөлү. Көпчүлүк учурларда, унааларды табигый сорттоо (биз аны чыгарылган жылы боюнча белгилейбиз) бизге ылайыктуу. Бирок кээде биздин кардарлардын арасында ылдам айдаганды жакшы көргөндөр болот. Эгерде биз алар үчүн машинелердин каталогун даярдап жаткан болсок, аларды максималдуу ылдамдык менен заказ кылуу керек. Java тorндеги компаратор - 3Мисалы, бизге 15% учурда ушундай сорттоо керек. CarБул өндүрүш жылынын ордуна ылдамдыгы боюнча табигый сорттоо үчүн жетиштүү эмес . Бирок биз кардарлардын 15% көңүл бурбай коё албайбыз. Биз эмне кылабыз? Бул жерде дагы бир интерфейс жардамга келет - Comparator. сыяктуу эле, Comparableал терилген. Айырмасы эмне? Comparablean objectтерибизди "салыштырууга" ылайыктуу кылат жана алар үчүн көпчүлүк учурда колдонула турган эң табигый сорт тартибин түзөт. Comparator- бул өзүнчө "салыштыруучу" класс (котормо бир аз олдоксон, бирок түшүнүктүү). CarЭгер кандайдыр бир конкреттүү сорттоону ишке ашыруу керек болсо, класска кирип , логиканы өзгөртүүнүн кереги жок compareTo(). Анын ордуна, биз өз программабызда өзүнчө компаратор класс түзүп, аны өзүбүзгө керектүү сорттоого үйрөтө алабыз!
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()- бул интерфейс ыкмасы Comparator, аны ишке ашыруу керек. Ал эки an objectти киргизет Carжана алардын максималдуу ылдамдыгын кадимки жол менен салыштырат (кемитүү жолу менен). Окшош compareTo(), ал санды кайтарат 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()Биз жөн гана салыштыруучу an objectти түзүп, аны иргеле турган тизме менен бирге методго өткөрүп беребиз . Киргизүү катары салыштыргычты алгандан кийин, метод класс sort()методунда аныкталган табигый сорттоону колдонбойт . Анын ордуна, ал өзүнө берилген салыштыргычтан сорттоо алгоритмин колдонот. Бул бизге кандай артыкчылыктарды берет? Биринчиден, жазылган code менен шайкештик. Көпчүлүк учурларда колдонула турган учурдагыны сактап, жаңы, өзгөчө сорттоо ыкмасын түздүк. Класска такыр тийген жокпуз . Ал ошол бойдон калды: compareTo()CarCarComparable
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();
   }

   //...геттеры, сеттеры, toString()

}
Экинчиден, ийкемдүүлүк. Каалаганча түрлөрүн кошо алабыз. Айталы, унааларды түсү, ылдамдыгы, салмагы боюнча же унаа Батман фильмдеринде канча жолу колдонулганы боюнча сорттоңуз. Бул жөн гана кошумча түзүү үчүн жетиштүү болуп саналат Comparator. Баары болду! Бүгүн сиз жумушта реалдуу долбоорлордо көп колдоно турган эки маанилүү механизмди үйрөндүңүз. Бирок, өзүңөр билгендей, практикасыз теория эч нерсе эмес. Ошондуктан, бorмиңизди бекемдеп, бир нече маселелерди чечүүгө убакыт келди! :)
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION