Сортировка коллекции объектов [дубликат]


этот вопрос уже есть ответ здесь:

  • Сортировка ArrayList объектов с помощью пользовательского порядка сортировки 9 ответов

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

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

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

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

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

9 56

9 ответов:

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

сборники.сортировка может быть вызвана с помощью пользовательского компаратора. И этот компаратор может быть реализован, чтобы разрешить сортировку в разных порядках сортировки. Вот пример (для вашей модели лица - с возрастом в виде целого числа):

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
}

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

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

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

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

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

вы также можете использовать BeanComparator из apache commons beanutils, например:

Collections.sort(personList, new BeanComparator("name"));

реализовать 3 различных типа компаратора.

вы можете добавить компаратор в команду сортировки. Компаратор, который вы определяете, будет сортировать элементы по имени, возрасту или чему-либо еще.

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

Коллекций.метод сортировки может быть вызван со вторым аргументом, который является компаратором для использования. Создайте 3 компаратора и используйте тот, который вы хотите, когда это необходимо.

Collections.sort(list , new Comparator() {
        public int compare(Object o1, Object o2) {
          ...
        }
      });

попросил очень похожий вопрос (о поиске, а не сортировке), возможно, есть какая-то полезная информация (я закончил с помощью enum что реализует Comparator поэтому я передаю enum значение в качестве селектора-компаратора).

используя lambdaj ( http://code.google.com/p/lambdaj/) Вы можете достичь того, что вы просите следующим образом:

сортировать (personList, on (Person.класс.)getName ());

сортировать (personList, on (Person.класс.)getAge());

сортировать (personList, on (Person.класс.)getCountry());