Компаратор java что это
Функция сравнения, которая налагает полное упорядочивание на некоторый набор объектов. Компараторы можно передать к методу вида (такой как Collections.sort или Arrays.sort ) позволить точное управление порядком сортировки. Компараторы могут также использоваться, чтобы управлять порядком определенных структур данных (такой как sorted sets или sorted maps ), или обеспечить упорядочивание для наборов объектов, у которых нет a natural ordering . Упорядочивание, наложенное компаратором, которому равняется c на ряде элементов, с которыми S, как говорят, является непротиворечивым, если и только если у c.compare(e1, e2)==0 есть то же самое булево значение как e1.equals(e2) для каждого e1 и e2 в S. Предостережение должно быть осуществлено при использовании компаратора, способного к наложению упорядочивания, непоследовательного с, равняется, чтобы упорядочить сортированный набор (или сортированная карта). Предположите сортированный набор (или сортированная карта) с явным компаратором, c используется с элементами (или ключи) оттянутый из набора S. Если упорядочивание, наложенное c на S, непоследовательно с, равняется, сортированный набор (или сортированная карта) будет вести себя «странно». В особенности сортированный набор (или сортированная карта) нарушит общий контракт для набора (или карта), который определяется с точки зрения equals. Например, предположите, что каждый добавляет два элемента a и b так, что (a.equals(b) && c.compare(a, b) != 0) к пустому TreeSet с компаратором c . Второе add работа возвратит true (и размер древовидного набора увеличится), потому что a и b не эквивалентны с точки зрения древовидного набора, даже при том, что это противоречит спецификации Set.add метод. Отметьте: Это — обычно хорошая идея для компараторов, чтобы также реализовать java.io.Serializable, поскольку они могут использоваться в качестве упорядочивания методов в сериализуемых структурах данных (как TreeSet , TreeMap ). Для структуры данных, чтобы сериализировать успешно, компаратор (если обеспечено) должен реализовать Serializable. Для математически наклоненного, отношение, которое определяет наложенное упорядочивание, которое данный компаратор c налагает на данный набор объектов, которые S:
Частное для этого полного порядка:
Это сразу следует из контракта для compare, что частное является отношением эквивалентности на S, и что наложенное упорядочивание является полным порядком на S. То, когда мы говорим, что упорядочивание, наложенное c на S, является непротиворечивым с, равняется, мы подразумеваем, что частное для упорядочивания является отношением эквивалентности, определенным объектами equals(Object) метод (ы):
В отличие от этого Comparable , компаратор может дополнительно разрешить сравнение нулевых параметров, поддерживая требования для отношения эквивалентности. Этот интерфейс является элементом Платформы Наборов Java.
Сводка метода
| Модификатор и Тип | Метод и Описание |
|---|---|
| int | compare(T o1, T o2) |
Сравнивает его два параметра за порядок.
Указывает, » ли некоторый другой объект равен» этому компаратору.
Деталь метода
сравниться
int compare(T o1, T o2)
Сравнивает его два параметра за порядок. Возвращает отрицательное целое число, нуль, или положительное целое число, поскольку первым параметром являются меньше чем, равный, или больше чем второе. В предшествующем описании нотации sgn( expression) определяет математическую сигнум-функцию, которая определяется, чтобы возвратить один из -1, 0, или 1 согласно тому, отрицательно ли значение выражения, нуль или положительно. Конструктор должен гарантировать что sgn(compare(x, y)) == -sgn(compare(y, x)) для всего x и y. (Это подразумевает, что compare(x, y) должен выдать исключение, если и только если compare(y, x) выдает исключение.) Конструктор должен также гарантировать, что отношение является переходным: ((compare(x, y)>0) && (compare(y, z)>0)) подразумевает compare(x, z)>0. Наконец, конструктор должен гарантировать, что compare(x, y)==0 подразумевает что sgn(compare(x, z))==sgn(compare(y, z)) для всего z. Это обычно имеет место, но не строго требуемое тот (compare(x, y)==0) == (x.equals(y)). Вообще говоря, любой компаратор, который нарушает это условие, должен ясно указать на этот факт. Рекомендуемый язык является «Примечанием: этот компаратор налагает упорядочивания, которые непоследовательны с, равняется.»
равняется
Указывает, » ли некоторый другой объект равен» этому компаратору. Этот метод должен повиноваться общему контракту Object.equals(Object) . Дополнительно, этот метод может возвратить true, только если указанный объект является также компаратором, и это налагает то же самое упорядочивание как этот компаратор. Таким образом, comp1.equals(comp2) подразумевает что sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2)) для каждой ссылки на объект o1 и o2. Отметьте, что всегда безопасно не переопределить Object.equals(Object). Однако, переопределение этого метода может, в некоторых случаях, улучшить производительность, позволяя программы решить, что два отличных компаратора налагают тот же самый порядок.
Платформа Java™
Стандарт Эд. 7
Представьте ошибку или функцию
Для дальнейшей ссылки API и документации разработчика, см. Java Документация SE . Та документация содержит более подробные, предназначенные разработчиком описания, с концептуальными краткими обзорами, определениями сроков, обходных решений, и рабочих примеров кода.
Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
31.20. Java – Comparator
И TreeSet, и TreeMap хранят элементы в отсортированном порядке. Однако именно компаратор в Java точно определяет, что такое отсортированный порядок.
Методы
Интерфейс Comparator в Java определяет два метода: compare() и equals(). Метод compare(), показанный здесь, сравнивает два элемента:
Метод Compare
int compare(Object obj1, Object obj2)
obj1 и obj2 — объекты, которые нужно сравнить. Этот метод возвращает ноль, если объекты равны. Он возвращает положительное значение, если obj1 больше, чем obj2. В противном случае возвращается отрицательное значение. При переопределении compare() вы можете изменить способ упорядочивания объектов. Например, для сортировки в обратном порядке вы можете создать компаратор, который изменит исход сравнения.
Метод Equals
Метод equals(), показанный здесь, проверяет, равен ли объект вызывающему компаратору.
boolean equals(Object obj)
obj — объект, подлежащий проверке на равенство. Метод возвращает true, если obj и вызывающий объект являются объектами Comparator и используют один и тот же порядок. В противном случае возвращается false.
Переопределять equals () не нужно, и большинство простых компараторов этого не сделают.
Пример
import java.util.*; class Dog implements Comparator, Comparable < private String name; private int age; Dog() < >Dog(String n, int a) < name = n; age = a; >public String getDogName() < return name; >public int getDogAge() < return age; >// Переопределяем метод compareTo public int compareTo(Dog d) < return (this.name).compareTo(d.name); >// Переопределяем метод compare для сортировки возраста public int compare(Dog d, Dog d1) < return d.age - d1.age; >> public class Example < public static void main(String args[]) < // Берём список элементов Dog Listlist = new ArrayList(); list.add(new Dog("Шегги", 3)); list.add(new Dog("Лэси", 2)); list.add(new Dog("Роджер", 10)); list.add(new Dog("Томми", 4)); list.add(new Dog("Тамми", 1)); Collections.sort(list); // Сортируем список массивов for(Dog a: list) // Выводим сортированный список имён System.out.print(a.getDogName() + ", "); // Сортируем список массивов, используя компаратор Collections.sort(list, new Dog()); System.out.println(" "); for(Dog a: list) // Выводим сортированный список возрастов System.out.print(a.getDogName() +" : "+ a.getDogAge() + ", "); > >
Получим следующий результат:
Лэси, Роджер, Шэгги, Тамми, Томми, Тамми : 1, Лэси : 2, Лэси : 3, Томми : 4, Роджер : 10,
Примечание: сортировка класса Arrays аналогична классу Collections.
Оглавление
- 1. Java – Самоучитель для начинающих
- 2. Java – Обзор языка
- 3. Java – Установка и настройка
- 4. Java – Синтаксис
- 5. Java – Классы и объекты
- 6. Java – Конструкторы
- 7. Java – Типы данных и литералы
- 8. Java – Типы переменных
- 9. Java – Модификаторы
- 10. Java – Операторы
- 11. Java – Циклы и операторы цикла
- 11.1. Java – Цикл while
- 11.2. Java – Цикл for
- 11.3. Java – Улучшенный цикл for
- 11.4. Java – Цикл do..while
- 11.5. Java – Оператор break
- 11.6. Java – Оператор continue
- 12. Java – Операторы принятия решений
- 12.1. Java – Оператор if
- 12.2. Java – Оператор if..else
- 12.3. Java – Вложенный оператор if
- 12.4. Java – Оператор switch..case
- 12.5. Java – Условный оператор (? 🙂
- 13. Java – Числа
- 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
- 13.2. Java – Метод compareTo()
- 13.3. Java – Метод equals()
- 13.4. Java – Метод valueOf()
- 13.5. Java – Метод toString()
- 13.6. Java – Метод parseInt()
- 13.7. Java – Метод Math.abs()
- 13.8. Java – Метод Math.ceil()
- 13.9. Java – Метод Math.floor()
- 13.10. Java – Метод Math.rint()
- 13.11. Java – Метод Math.round()
- 13.12. Java – Метод Math.min()
- 13.13. Java – Метод Math.max()
- 13.14. Java – Метод Math.exp()
- 13.15. Java – Метод Math.log()
- 13.16. Java – Метод Math.pow()
- 13.17. Java – Метод Math.sqrt()
- 13.18. Java – Метод Math.sin()
- 13.19. Java – Метод Math.cos()
- 13.20. Java – Метод Math.tan()
- 13.21. Java – Метод Math.asin()
- 13.22. Java – Метод Math.acos()
- 13.23. Java – Метод Math.atan()
- 13.24. Java – Метод Math.atan2()
- 13.25. Java – Метод Math.toDegrees()
- 13.26. Java – Метод Math.toRadians()
- 13.27. Java – Метод Math.random()
- 14. Java – Символы
- 14.1. Java – Метод Character.isLetter()
- 14.2. Java – Метод Character.isDigit()
- 14.3. Java – Метод Character.isWhitespace()
- 14.4. Java – Метод Character.isUpperCase()
- 14.5. Java – Метод Character.isLowerCase()
- 14.6. Java – Метод Character.toUpperCase()
- 14.7. Java – Метод Character.toLowerCase()
- 14.8. Java – Метод Character.toString()
- 15. Java – Строки
- 15.1. Java – Метод charAt()
- 15.2. Java – Метод compareTo()
- 15.3. Java – Метод compareToIgnoreCase()
- 15.4. Java – Метод concat()
- 15.5. Java – Метод contentEquals()
- 15.6. Java – Метод copyValueOf()
- 15.7. Java – Метод endsWith()
- 15.8. Java – Метод equals()
- 15.9. Java – Метод equalsIgnoreCase()
- 15.10. Java – Метод getBytes()
- 15.11. Java – Метод getChars()
- 15.12. Java – Метод hashCode()
- 15.13. Java – Метод indexOf()
- 15.14. Java – Метод intern()
- 15.15. Java – Метод lastIndexOf()
- 15.16. Java – Метод length()
- 15.17. Java – Метод matches()
- 15.18. Java – Метод regionMatches()
- 15.19. Java – Метод replace()
- 15.20. Java – Метод replaceAll()
- 15.21. Java – Метод replaceFirst()
- 15.22. Java – Метод split()
- 15.23. Java – Метод startsWith()
- 15.24. Java – Метод subSequence()
- 15.25. Java – Метод substring()
- 15.26. Java – Метод toCharArray()
- 15.27. Java – Метод toLowerCase()
- 15.28. Java – Метод toString()
- 15.29. Java – Метод toUpperCase()
- 15.30. Java – Метод trim()
- 15.31. Java – Метод valueOf()
- 15.32. Java – Классы StringBuilder и StringBuffer
- 15.32.1. Java – Метод append()
- 15.32.2. Java – Метод reverse()
- 15.32.3. Java – Метод delete()
- 15.32.4. Java – Метод insert()
- 15.32.5. Java – Метод replace()
- 16. Java – Массивы
- 17. Java – Дата и время
- 18. Java – Регулярные выражения
- 19. Java – Методы
- 20. Java – Потоки ввода/вывода, файлы и каталоги
- 20.1. Java – Класс ByteArrayInputStream
- 20.2. Java – Класс DataInputStream
- 20.3. Java – Класс ByteArrayOutputStream
- 20.4. Java – Класс DataOutputStream
- 20.5. Java – Класс File
- 20.6. Java – Класс FileReader
- 20.7. Java – Класс FileWriter
- 21. Java – Исключения
- 21.1. Java – Встроенные исключения
- 22. Java – Вложенные и внутренние классы
- 23. Java – Наследование
- 24. Java – Переопределение
- 25. Java – Полиморфизм
- 26. Java – Абстракция
- 27. Java – Инкапсуляция
- 28. Java – Интерфейсы
- 29. Java – Пакеты
- 30. Java – Структуры данных
- 30.1. Java – Интерфейс Enumeration
- 30.2. Java – Класс BitSet
- 30.3. Java – Класс Vector
- 30.4. Java – Класс Stack
- 30.5. Java – Класс Dictionary
- 30.6. Java – Класс Hashtable
- 30.7. Java – Класс Properties
- 31. Java – Коллекции
- 31.1. Java – Интерфейс Collection
- 31.2. Java – Интерфейс List
- 31.3. Java – Интерфейс Set
- 31.4. Java – Интерфейс SortedSet
- 31.5. Java – Интерфейс Map
- 31.6. Java – Интерфейс Map.Entry
- 31.7. Java – Интерфейс SortedMap
- 31.8. Java – Класс LinkedList
- 31.9. Java – Класс ArrayList
- 31.10. Java – Класс HashSet
- 31.11. Java – Класс LinkedHashSet
- 31.12. Java – Класс TreeSet
- 31.13. Java – Класс HashMap
- 31.14. Java – Класс TreeMap
- 31.15. Java – Класс WeakHashMap
- 31.16. Java – Класс LinkedHashMap
- 31.17. Java – Класс IdentityHashMap
- 31.18. Java – Алгоритмы Collection
- 31.19. Java – Iterator и ListIterator
- 31.20. Java – Comparator
- 32. Java – Дженерики
- 33. Java – Сериализация
- 34. Java – Сеть
- 34.1. Java – Обработка URL
- 35. Java – Отправка Email
- 36. Java – Многопоточность
- 36.1. Java – Синхронизация потоков
- 36.2. Java – Межпоточная связь
- 36.3. Java – Взаимная блокировка потоков
- 36.4. Java – Управление потоками
- 37. Java – Основы работы с апплетами
- 38. Java – Javadoc
Чем отличается Comparator от Comparable?
Интерфейс Comparable определяет естественный порядок среди объектов. Java Collections Framework активно использует этот порядок. По нему упорядочены элементы SortedSet / SortedMap , им упорядочиваются элементы списков и массивов в методе sort().
Порядок определяется единственным методом compareTo . Отрицательный результат означает что текущий объект «меньше» чем переданный параметром, 0 – равен, положительный – больше. Рекомендуется чтобы равные с точки зрения equals объекты всегда были равны с точки зрения compareTo .
С математической точки зрения это должен быть линейный порядок. Он требует выполнения четырех свойств:
1. Антирефлексивность: x.compareTo(x) всегда 0 ;
2. Антисимметричность: если x.compareTo(y) > 0 , то y.compareTo(x) < 0 ;
3. Транзитивность: если x.compareTo(y) > 0 и y.compareTo(z) > 0 , то x.compareTo(z) > 0 ;
4. Полнота: отношение определено для любых объектов класса (кроме null ).
Интерфейс Comparator – это логика Comparable, вынесенная в отдельный объект. Компаратор реализует паттерн Стратегия. Большинство платформенных методов, использующих Comparable имеют перегруженный вариант с не-comparable объектом и внешним компаратором.
Comparator бывает полезен, когда класс предоставлен сторонней библиотекой, и нет возможности его менять. Другой случай – особая логика упорядочивания, не свойственная классу объектов в общем, но нужная для отдельной ситуации.
Кроме основного метода compare() , в компараторе есть набор утилитарных методов для комбинирования и модификации компараторов. Все они возвращают новый компаратор, позволяя сделать его иммутабельным.
Компаратор java что это
В прошлой теме была рассмотрена работа коллекции TreeSet, типизированной объектами String. При добавлении новых элементов объект TreeSet автоматически проводит сортировку, помещая новый объект на правильное для него место. Однако со строками все понятно. А что если бы мы использовали не строки, а свои классы, например, следующий класс Person:
class Person < private String name; Person(String name)< this.name=name; >String getName() >
Объект TreeSet мы не сможем типизировать данным классом, поскольку в случае добавления объектов TreeSet не будет знать, как их сравнивать, и следующий кусок кода не будет работать:
TreeSet people = new TreeSet(); people.add(new Person("Tom"));
При выполнении этого кода мы столкнемся с ошибкой, которая скажет, что объект Person не может быть преобразован к типу java.lang.Comparable.
Для того, чтобы объекты Person можно было сравнить и сортировать, они должны применять интерфейс Comparable . При применении интерфейса он типизируется текущим классом. Применим его к классу Person:
class Person implements Comparable < private String name; Person(String name)< this.name = name; >String getName() public int compareTo(Person p) < return name.compareTo(p.getName()); >>
Интерфейс Comparable содержит один единственный метод int compareTo(E item) , который сравнивает текущий объект с объектом, переданным в качестве параметра. Если этот метод возвращает отрицательное число, то текущий объект будет располагаться перед тем, который передается через параметр. Если метод вернет положительное число, то, наоборот, после второго объекта. Если метод возвратит ноль, значит, оба объекта равны.
В данном случае мы не возвращаем явным образом никакое число, а полагаемся на встроенный механизм сравнения, который есть у класса String. Но мы также можем определить и свою логику, например, сравнивать по длине имени:
public int compareTo(Person p)
Теперь мы можем типизировать TreeSet типом Person и добавлять в дерево соответствующие объекты:
TreeSet people = new TreeSet(); people.add(new Person("Tom"));
Интерфейс Comparator
Однако перед нами может возникнуть проблема, что если разработчик не реализовал в своем классе, который мы хотим использовать, интерфейс Comparable, либо реализовал, но нас не устраивает его функциональность, и мы хотим ее переопределить? На этот случай есть еще более гибкий способ, предполагающий применение интерфейса Comparator.
Интерфейс Comparator содержит ряд методов, ключевым из которых является метод compare() :
public interface Comparator < int compare(T a, T b); // остальные методы >
Метод compare также возвращает числовое значение — если оно отрицательное, то объект a предшествует объекту b, иначе — наоборот. А если метод возвращает ноль, то объекты равны. Для применения интерфейса нам вначале надо создать класс компаратора, который реализует этот интерфейс:
class PersonComparator implements Comparator < public int compare(Person a, Person b)< return a.getName().compareTo(b.getName()); >>
Здесь опять же проводим сравнение по строкам. Теперь используем класс компаратора для создания объекта TreeSet:
PersonComparator pcomp = new PersonComparator(); TreeSet people = new TreeSet(pcomp); people.add(new Person(«Tom»)); people.add(new Person(«Nick»)); people.add(new Person(«Alice»)); people.add(new Person(«Bill»)); for(Person p : people)
Для создания TreeSet здесь используется одна из версий конструктора, которая в качестве параметра принимает компаратор. Теперь вне зависимости от того, реализован ли в классе Person интерфейс Comparable, логика сравнения и сортировки будет использоваться та, которая определена в классе компаратора.
Сортировка по нескольким критериям
Начиная с JDK 8 в механизм работы компараторов были внесены некоторые дополнения. В частности, теперь мы можем применять сразу несколько компараторов по принципу приоритета. Например, изменим класс Person следующим образом:
class Person < private String name; private int age; public Person(String n, int a)< name=n; age=a; >String getName() int getAge() >
Здесь добавлено поле для хранения возраста пользователя. И, допустим, нам надо отсортировать пользователей по имени и по возрасту. Для этого определим два компаратора:
class PersonNameComparator implements Comparator < public int compare(Person a, Person b)< return a.getName().compareTo(b.getName()); >> class PersonAgeComparator implements Comparator < public int compare(Person a, Person b)< if(a.getAge()>b.getAge()) return 1; else if(a.getAge() < b.getAge()) return -1; else return 0; >>
Интерфейс компаратора определяет специальный метод по умолчанию thenComparing , который позволяет использовать цепочки компараторов для сортировки набора:
Comparator pcomp = new PersonNameComparator().thenComparing(new PersonAgeComparator()); TreeSet people = new TreeSet(pcomp); people.add(new Person(«Tom», 23)); people.add(new Person(«Nick»,34)); people.add(new Person(«Tom»,10)); people.add(new Person(«Bill»,14)); for(Person p : people)
Bill 14 Nick 34 Tom 10 Tom 23
В данном случае сначала применяется сортировка по имени, а потом по возрасту.
