Сортировать ArrayList пользовательских объектов по свойству - PullRequest
1067 голосов
/ 07 мая 2010

Я читал о сортировке списков ArrayLists с использованием Comparator, но во всех примерах люди использовали compareTo, который согласно некоторым исследованиям является методом для строк.

Я хотел отсортировать ArrayList пользовательских объектов по одному из их свойств: объекту Date (getStartDay()). Обычно я сравниваю их по item1.getStartDate().before(item2.getStartDate()), поэтому мне было интересно, смогу ли я написать что-то вроде:

public class CustomComparator {
    public boolean compare(Object object1, Object object2) {
        return object1.getStartDate().before(object2.getStartDate());
    }
}

public class RandomName {
    ...
    Collections.sort(Database.arrayList, new CustomComparator);
    ...
}

Ответы [ 25 ]

1447 голосов
/ 07 мая 2010

Поскольку Date реализует Comparable, он имеет метод compareTo, как и String.

Так что ваш кастом Comparator может выглядеть так:

public class CustomComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
}

Метод compare() должен возвращать int, поэтому вы не можете напрямую вернуть boolean, как планировали в любом случае.

Ваш код сортировки будет примерно таким, как вы написали:

Collections.sort(Database.arrayList, new CustomComparator());

Немного более короткий способ написать все это, если вам не нужно повторно использовать ваш компаратор, это написать его как встроенный анонимный класс:

Collections.sort(Database.arrayList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
});

С

Теперь вы можете написать последний пример в более короткой форме, используя лямбда-выражение для Comparator:

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

И List имеет метод sort(Comparator), так что вы можете сократить его еще больше:

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

Это настолько распространенная идиома, что есть встроенный метод для генерации Comparator для класса с ключом Comparable:

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));

Все это эквивалентные формы.

190 голосов
/ 07 мая 2010

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

Два примера:

public class Number implements Comparable<Number> {
    private int value;

    public Number(int value) { this.value = value; }
    public int compareTo(Number anotherInstance) {
        return this.value - anotherInstance.value;
    }
}

public class Chair {
    private int weight;
    private int height;

    public Chair(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }
    /* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getWeight() - chair2.getWeight();
    }
}
class ChairHeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getHeight() - chair2.getHeight();
    }
}

Использование:

List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);

List<Chair> chairs = new ArrayList<Chair>();
// Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
// Sort by height:
Collections.sort(chairs, new ChairHeightComparator());

// You can also create anonymous comparators;
// Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
    public int compare(Chair chair1, Chair chair2) {
        ...
    }
});
153 голосов
/ 06 мая 2012

Для сортировки ArrayList вы можете использовать следующий фрагмент кода:

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});
42 голосов
/ 07 мая 2010

Да, вы можете. Существует два варианта сравнения элементов: интерфейс Comparable и интерфейс Comparator .

Оба эти интерфейса допускают различное поведение. Comparable позволяет вам заставить объект действовать так, как вы только что описали Strings (фактически String реализует Comparable). Второй, Comparator, позволяет вам делать то, что вы просите. Вы бы сделали это так:

Collections.sort(myArrayList, new MyComparator());

Это заставит метод Collections.sort использовать ваш компаратор для механизма сортировки. Если объекты в ArrayList реализуют сравнимо, вы можете вместо этого сделать что-то вроде этого:

Collections.sort(myArrayList);

Класс Collections содержит ряд этих полезных, общих инструментов.

36 голосов
/ 05 сентября 2014

JAVA 8 лямбда-выражение

Collections.sort(studList, (Student s1, Student s2) ->{
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});

OR

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)
30 голосов
/ 13 марта 2014

В Java 8 вы можете использовать ссылку на метод для вашего компаратора:

import static java.util.Comparator.comparing;

Collections.sort(list, comparing(MyObject::getStartDate));
14 голосов
/ 12 марта 2014

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

Вы можете попробовать решить эти задачи с помощью LambdaJ . Вы можете найти его здесь: http://code.google.com/p/lambdaj/

Вот вам пример:

Итеративная сортировка

List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
});

Сортировка с лямбдой

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

Конечно, такая красота влияет на производительность (в среднем в 2 раза), но вы можете найти более читаемый код?

13 голосов
/ 03 апреля 2012
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

public class test {

public static class Person {
    public String name;
    public int id;
    public Date hireDate;

    public Person(String iname, int iid, Date ihireDate) {
        name = iname;
        id = iid;
        hireDate = ihireDate;
    }

    public String toString() {
        return name + " " + id + " " + hireDate.toString();
    }

    // Comparator
    public static class CompId implements Comparator<Person> {
        @Override
        public int compare(Person arg0, Person arg1) {
            return arg0.id - arg1.id;
        }
    }

    public static class CompDate implements Comparator<Person> {
        private int mod = 1;
        public CompDate(boolean desc) {
            if (desc) mod =-1;
        }
        @Override
        public int compare(Person arg0, Person arg1) {
            return mod*arg0.hireDate.compareTo(arg1.hireDate);
        }
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SimpleDateFormat df = new SimpleDateFormat("mm-dd-yyyy");
    ArrayList<Person> people;
    people = new ArrayList<Person>();
    try {
        people.add(new Person("Joe", 92422, df.parse("12-12-2010")));
        people.add(new Person("Joef", 24122, df.parse("1-12-2010")));
        people.add(new Person("Joee", 24922, df.parse("12-2-2010")));
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    Collections.sort(people, new Person.CompId());
    System.out.println("BY ID");
    for (Person p : people) {
        System.out.println(p.toString());
    }

    Collections.sort(people, new Person.CompDate(false));
    System.out.println("BY Date asc");
    for (Person p : people) {
        System.out.println(p.toString());
    }
    Collections.sort(people, new Person.CompDate(true));
    System.out.println("BY Date desc");
    for (Person p : people) {
        System.out.println(p.toString());
    }

}

}
9 голосов
/ 28 мая 2016

Лучший простой способ с JAVA 8 для английского алфавита

Реализация класса

public class NewspaperClass implements Comparable<NewspaperClass>{
   public String name;

   @Override
   public int compareTo(NewspaperClass another) {
      return name.compareTo(another.name);
   }
}

Сортировка

  Collections.sort(Your List);

Если вы хотите отсортировать по алфавиту, который содержит не английские символы, вы можете использовать Locale ... Ниже кода используйте турецкую сортировку символов ...

Реализация класса

public class NewspaperClass implements Comparator<NewspaperClass> {
   public String name;
   public Boolean isUserNewspaper=false;
   private Collator trCollator = Collator.getInstance(new Locale("tr_TR"));



   @Override
   public int compare(NewspaperClass lhs, NewspaperClass rhs) {
      trCollator.setStrength(Collator.PRIMARY);
      return trCollator.compare(lhs.name,rhs.name);
   }
}

Сортировка

Collections.sort(your array list,new NewspaperClass());
7 голосов
/ 15 декабря 2015

Справочник по функциям и методам

Метод Collections.sort может сортировать List, используя Comparator, который вы передаете. Это Comparator может быть реализовано с использованием метода Comparator.comparing, где вы можете передать ссылку на метод как необходимый Function. К счастью, реальный код намного проще и короче, чем это описание.

Для Java 8:

Collections.sort(list, comparing(ClassName::getName));

или

Collections.sort(list, comparing(ClassName::getName).reversed());

Другой способ это

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...