Компаратор, сортиращи колекции - 1

„Здрасти, Амиго!“

„Здравей, Билаабо!“

„Днес ще разгледаме малка, но интересна и полезна тема: сортиране на колекции.“

"Сортиране? Чувал съм нещо за това."

„Преди много време всеки програмист трябваше да може да пише алгоритми за сортиране. Можеше и трябваше да ги пише. Но тези дни отминаха. Днес писането на собствен code за сортиране се счита за лоша форма, точно Howто пренаписването на всичко друго, което вече е извършено е изобретен."

"В Java (и други езици за програмиране) сортирането вече е реализирано.  Вашата задача е да се научите How правилно да използвате това, което вече съществува. "

"ДОБРЕ."

„ Помощният клас Collections има статичен метод за сортиране, който се използва за сортиране на колекции or по-точно списъци. Елементите в Maps и Sets нямат ред/индекс, така че няма Howво да се сортира.“

"Да, помня. Използвах този метод веднъж, за да сортирам списък с числа."

"Страхотно. Но този метод е много по-мощен, отколкото изглежда на пръв поглед. Той може да сортира не само числа, но и всяHowви обекти, въз основа на всяHowви критерии. Два интерфейса помагат на метода да направи това: Comparable и Comparator . "

„Понякога трябва да сортирате обекти, а не числа. Да предположим например, че имате списък с хора и искате да ги сортирате по възраст. Имаме интерфейс Comparable за това.“

„Нека първо ви покажа един пример и тогава всичко ще стане по-ясно:“

Пример
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;
}
}
Пример за това How може да се използва:
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);
}

„За да сортирате обекти, първо трябва да знаете How да ги сравнявате. За целта използваме Comparable. Интерфейсът Comparable е общ, което означава, че приема аргумент тип. Има само един общ метод: compareTo(T o). Този метод сравнява текущия обект (this) и обект, предаден като аргумент (o). С други думи, трябва да внедрим този метод в нашия клас и след това да го използваме, за да сравним текущия обект (this) с подавания обект. "

„И How работи compareTo? Очаквах, че ще върне true or false в зависимост от това дали предаваният обект е по-голям or по-малък.“

„Тук нещата са по-трудни. Методът compareTo не връща true/false. Вместо това той връща int. Това всъщност се прави за простота.

„Когато компютър трябва да определи дали едно число е по-голямо от друго, той просто изважда второто число от първото и след това разглежда резултата. Ако резултатът е 0, тогава числата са равни. Ако резултатът е по-малък от нула , тогава второто число е по-голямо. И ако резултатът е по-голям от нула, тогава първото число е по-голямо."

„Същата логика се прилага и тук. Според спецификацията методът compareTo трябва да върне нула, ако сравняваните обекти са равни. Ако методът compareTo върне число, по-голямо от нула, тогава нашият обект е по-голям от подавания обект. „Ако compareTo методът връща число, по-малко от нула, тогава 'this' е по-малко от предадения обект."

— Това е малко странно.

„Да, но ако сравнявате обекти просто въз основа на няHowво числово свойство, тогава можете просто да върнете разликата между тях, като извадите единия от другия. Точно Howто беше напequalsо в примера по-горе.“

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

„Мисля, че разбирам всичко. Но може би не. Но почти всичко.“

„Страхотно. Сега нека разгледаме по-практичен проблем. Да предположим, че сте написали готин уебсайт за производство на дамско облекло в Китай. Използвате клас Жена, за да опишете клиентите си. Дори сте направor уеб page с table, където можете да ги видите всички . Но има проблем..."

„Обектът „Вашата жена“ съдържа не само възраст, но и цял куп други данни: име, фамorя, височина, тегло, брой деца и т.н.“

„Таблицата с потребители има много колони и тук е въпросът: How сортирате потребителите си по различни критерии? По тегло, по възраст, по фамorя?“

„Хм. Да, често виждам таблици, които ви позволяват да сортирате по колона. И така, How го правите?“

„За това имаме втория интерфейс, за който исках да ви разкажа днес: интерфейсът Comparator. Той също има метод за сравнение, но отнема два аргумента, а не един: int compare(T o1, T o2). Ето How върши работа:"

Пример
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;
}
}
Пример за това How може да се използва:
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, и всеки от тях да сравнява различни свойства? Tagло в един, възраст в друг и височина в трети?“

— Да, много е просто и удобно.

„Ние просто извикваме метода Collections.sort , като предаваме списък с обекти и друг специален обект като втори аргумент, който имплементира интерфейса Comparator и ви казва How правилно да сравнявате двойки обекти в процеса на сортиране.“

„Хм. Мисля, че разбирам всичко. Нека опитам. Да кажем, че трябва да сортирам потребителите по тегло. Ще бъде нещо подобно:“

Пример за сортиране на потребители по тегло:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

"Да точно."

„Чудесно. Но Howво ще стане, ако искам да сортирам в обратен ред?“

"Помислете за това. Отговорът е много прост!"

„Разбрах го! Ето така:“

Сортиране във възходящ ред:
return o1.weight - o2.weight;
Сортиране в низходящ ред:
return o2.weight – o1.weight;

"Точно. Браво."

"И ако искам да сортирам по фамorя? Как да сортирам низове, Билаабо?"

"Класът String вече имплементира метода compareTo. Просто трябва да го извикате:"

Пример за сортиране на потребители по име:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

„Това беше страхотен урок, Билаабо. Благодаря ти много.“

— И на теб благодаря, приятелю!