Вопрос-ответ

Sorting a collection of objects [duplicate]

Сортировка коллекции объектов

Если у меня есть простой список строк:

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>();

И я хочу сортировать ее иногда по имени, иногда по возрасту, иногда по стране.

Какой самый простой способ добиться этого?

Я знаю, что могу реализовать сопоставимый интерфейс, но это, кажется, ограничивает меня сортировкой по одному определенному свойству.

Переведено автоматически
Ответ 1

Коллекции.сортировка может вызываться с помощью пользовательского компаратора. И этот компаратор может быть реализован для обеспечения сортировки в разных порядках сортировки. Вот пример (для вашей модели 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;
}
}

И вы используете это таким образом (предполагая, что persons - это поле):

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
}
Ответ 2

Реализуйте интерфейс Comparator (один раз для каждого отдельного порядка сортировки) и используйте метод Collections.sort(), который принимает Comparator в качестве дополнительного параметра.

Ответ 3

Спасибо ответчикам. Для пользы других я хотел бы включить полный пример.

Решение заключается в создании следующих дополнительных классов:

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());
Ответ 4

Способ сделать это в Java 8 заключается в использовании List.sort следующим образом:

personList.sort(Comparator.comparing(Person::getName));

Процитирую Стюарта Маркса в его ответе здесь.


В этом большое преимущество List.sort(cmp) метода расширения по сравнению с Collections.sort(list, cmp). Может показаться, что это всего лишь небольшое синтаксическое преимущество, заключающееся в возможности записи myList.sort(cmp) вместо Collections.sort(myList, cmp). Разница в том, что myList.sort(cmp), являясь методом расширения интерфейса, может быть переопределен конкретной List реализацией. Например, ArrayList.sort(cmp) сортирует список на месте, используя Arrays.sort() тогда как реализация по умолчанию реализует старую технику копирования-сортировки-обратного копирования.


2023-09-25 18:31 java collections