Ответ 1
Внедрите Comparator интерфейс (один раз для каждого другого порядка сортировки) и используйте Collections.sort(), который использует Компаратор как дополнительный параметр.
Если у меня есть простой список строк:
List<String> stringList = new ArrayList<String>();
Я могу сортировать его с помощью:
Collections.sort(stringList);
Но предположим, что у меня есть класс Person:
public class Person
{
private String name;
private Integer age;
private String country;
}
И его список:
List<Person> personList = new ArrayList<Person>();
И я хочу сортировать его по имени, иногда по возрасту, иногда по странам.
Каков самый простой способ сделать это?
Я знаю, что я могу реализовать интерфейс Comparable, но это, по-видимому, ограничивает меня сортировкой по одному конкретному свойству.
Внедрите Comparator интерфейс (один раз для каждого другого порядка сортировки) и используйте Collections.sort(), который использует Компаратор как дополнительный параметр.
Collections.sort можно вызвать с помощью специализированного компаратора. И этот компаратор может быть реализован, чтобы сортировать в разных порядках сортировки. Вот пример (для вашей модели Person - с возрастом как целое):
public class FlexiblePersonComparator implements Comparator<Person> {
public enum Order {Name, Age, Country}
private Order sortingBy = Name;
@Override
public int compare(Person person1, Person person2) {
switch(sortingBy) {
case Name: return person1.name.compareTo(person2.name);
case Age: return person1.age.compareTo(person2.age);
case Country: return person1.country.compareTo(person2.country);
}
throw new RuntimeException("Practically unreachable code, can't be thrown");
}
public void setSortingBy(Order sortBy) {
this.sortingBy = sortingBy;
}
}
И вы используете его так (предполагая, что люди - это поле):
public void sortPersonsBy(FlexiblePersonComparator.Order sortingBy) {
List<Person> persons = this.persons; // useless line, just for clarification
FlexiblePersonComparator comparator = new FlexiblePersonComparator();
comparator.setSortingBy(sortingBy);
Collections.sort(persons, comparator); // now we have a sorted list
}
Благодаря ответчикам. В интересах других я хотел бы привести полный пример.
Решением является создание следующих дополнительных классов:
public class NameComparator implements Comparator<Person>
{
public int compare(Person o1, Person o2)
{
return o1.getName().compareTo(o2.getName());
}
}
public class AgeComparator implements Comparator<Person>
{
public int compare(Person o1, Person o2)
{
return o1.getAge().compareTo(o2.getAge());
}
}
public class CountryComparator implements Comparator<Person>
{
public int compare(Person o1, Person o2)
{
return o1.getCountry().compareTo(o2.getCountry());
}
}
Затем список можно отсортировать следующим образом:
Collections.sort(personList, new NameComparator());
Collections.sort(personList, new AgeComparator());
Collections.sort(personList, new CountryComparator());
Способ Java 8 - это использовать List.sort
следующим образом:
personList.sort(Comparator.comparing(Person::getName));
Процитировать Stuart Marks в своем ответе на здесь.
Это большое преимущество метода расширения
List.sort(cmp)
по сравнению сCollections.sort(list, cmp)
. Может показаться, что это просто небольшое синтаксическое преимущество, заключающееся в возможности писатьmyList.sort(cmp)
вместоCollections.sort(myList, cmp)
. Разница в том, чтоmyList.sort(cmp)
, являющийся методом расширения интерфейса, может быть переопределен конкретной реализациейList
. Например,ArrayList.sort(cmp)
сортирует список на месте с помощьюArrays.sort()
, тогда как реализация по умолчанию реализует старый метод копирования-сортировки-копирования.
Вы также можете использовать BeanComparator от apache commons beanutils, например:
Collections.sort(personList, new BeanComparator("name"));
Реализовать 3 разных типа компаратора.
вы можете добавить компаратор к команде sort. Определяющий компаратор будет сортировать элементы по имени, возрасту или тому, что когда-либо.
Collections.sort(list, new Comparator() {
public int compare(Object arg0, Object arg1) {
if (!(arg0 instanceof Person)) {
return -1;
}
if (!(arg1 instanceof Person)) {
return -1;
}
Person pers0 = (Person)arg0;
Person pers1 = (Person)arg1;
// COMPARE NOW WHAT YOU WANT
// Thanks to Steve Kuo for your comment!
return pers0.getAge() - pers1.getAge();
}
});
Метод Collections.sort может быть вызван вторым аргументом, который используется компаратором. Создайте 3 компаратора и используйте тот, который вы хотите, когда это необходимо.
Collections.sort(list , new Comparator() {
public int compare(Object o1, Object o2) {
...
}
});
Я задал очень похожий вопрос (о поиске, а не сортировке), возможно, есть какая-то полезная информация (в итоге я использовал enum
, который реализует Comparator
поэтому я передаю значение enum
в качестве селектора компаратора).
Используя lambdaj (http://code.google.com/p/lambdaj/), вы можете добиться того, что вы спрашиваете, следующим образом:
sort (personList, on (Person.class).getName());
sort (personList, on (Person.class).getAge());
sort (personList, on (Person.class).getCountry());