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

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

Я хочу сортировать ArrayList<Contact> contactArray. Contact - это класс, который содержит четыре поля: имя, домашний номер, номер мобильного телефона и адрес. Я хочу сортировать по name.

Как я могу написать пользовательскую функцию сортировки для этого?

Ответы

Ответ 1

Вот учебник по упорядочению объектов:

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


Существует несколько способов сортировки ArrayList. Если вы хотите определить естественный (по умолчанию) порядок, тогда вам нужно позволить Contact реализовать Comparable. Предполагая, что вы хотите сортировать по умолчанию на name, тогда do (nullchecks опущено для простоты):

public class Contact implements Comparable<Contact> {

    private String name;
    private String phone;
    private Address address;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }

    // Add/generate getters/setters and other boilerplate.
}

чтобы вы могли просто сделать

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

Collections.sort(contacts);

Если вы хотите определить внешний контролируемый порядок (который переопределяет естественный порядок), вам необходимо создать Comparator:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Now sort by address instead of name (default).
Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

Вы даже можете определить Comparator в самом Contact, чтобы вы могли повторно использовать их, а не воссоздавать их каждый раз:

public class Contact {

    private String name;
    private String phone;
    private Address address;

    // ...

    public static Comparator<Contact> COMPARE_BY_PHONE = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.phone.compareTo(other.phone);
        }
    };

    public static Comparator<Contact> COMPARE_BY_ADDRESS = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.address.compareTo(other.address);
        }
    };

}

который можно использовать следующим образом:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Sort by address.
Collections.sort(contacts, Contact.COMPARE_BY_ADDRESS);

// Sort later by phone.
Collections.sort(contacts, Contact.COMPARE_BY_PHONE);

И чтобы сливать верх, вы можете использовать общий javabean компаратор:

public class BeanComparator implements Comparator<Object> {

    private String getter;

    public BeanComparator(String field) {
        this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
    }

    public int compare(Object o1, Object o2) {
        try {
            if (o1 != null && o2 != null) {
                o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
                o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
            }
        } catch (Exception e) {
            // If this exception occurs, then it is usually a fault of the developer.
            throw new RuntimeException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
        }

        return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));
    }

}

который вы можете использовать следующим образом:

// Sort on "phone" field of the Contact bean.
Collections.sort(contacts, new BeanComparator("phone"));

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

Ответ 2

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

Collection.sort(yourList, Comparator.comparing(YourClass::getFieldToSortOn));

или поскольку у List теперь есть метод sort

yourList.sort(Comparator.comparing(YourClass::getFieldToSortOn));

Объяснение:

Так как Java 8, функциональные интерфейсы (интерфейсы только с одним абстрактным методом - они могут иметь больше стандартных или статических методов), могут быть легко реализованы с помощью:

Так как Comparator<T> имеет только один абстрактный метод int compare(T o1, T o2), это функциональный интерфейс.

Итак, вместо (пример из @BalusC ответ)

Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

мы можем уменьшить этот код до:

Collections.sort(contacts, (Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress());
});

Мы можем упростить эту (или любую) лямбду, пропустив

  • типы аргументов (Java выведет их на основе подписи метода)
  • или {return... }

Итак, вместо

(Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress();
}

мы можем написать

(one, other) -> one.getAddress().compareTo(other.getAddress())

Также теперь Comparator имеет статические методы, такие как comparing(FunctionToComparableValue) или comparing(FunctionToValue, ValueComparator), которые мы могли бы использовать, чтобы легко создавать Компараторы, которые должны сравнивать некоторые конкретные значения от объектов.

Другими словами, мы можем переписать выше код как

Collections.sort(contacts, Comparator.comparing(Contact::getAddress)); 
//assuming that Address implements Comparable (provides default order).

Ответ 3

Эта страница сообщает вам все, что вам нужно знать о сортировке коллекций, таких как ArrayList.

В основном вам нужно

  • создайте класс Contact для интерфейса Comparable
    • создание метода public int compareTo(Contact anotherContact) внутри него.
  • Как только вы сделаете это, вы можете просто позвонить Collections.sort(myContactList);,
    • где myContactList - ArrayList<Contact> (или любой другой набор Contact).

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

Пример:

public class Contact implements Comparable<Contact> {

    ....

    //return -1 for less than, 0 for equals, and 1 for more than
    public compareTo(Contact anotherContact) {
        int result = 0;
        result = getName().compareTo(anotherContact.getName());
        if (result != 0)
        {
            return result;
        }
        result = getNunmber().compareTo(anotherContact.getNumber());
        if (result != 0)
        {
            return result;
        }
        ...
    }
}

Ответ 4

BalusC и bguiz уже дали очень полные ответы о том, как использовать встроенные компараторы Java.

Я просто хочу добавить, что google-коллекции имеют Ordering, который является более "мощным", чем стандартные компараторы. Возможно, стоит проверить. Вы можете делать классные вещи, такие как составление заказов, их изменение, упорядочение в зависимости от результата функции для ваших объектов...

Здесь - это сообщение в блоге, в котором упоминаются некоторые из его преимущества.

Ответ 5

Вам нужно создать классы контактов Comparable, а затем реализовать метод compareTo(Contact). Таким образом, Collections.sort сможет сортировать их для вас. На странице, с которой я связан, compareTo 'возвращает отрицательное целое число, ноль или положительное целое число, так как этот объект меньше, равен или больше указанного объекта.'

Например, если вы хотите сортировать по имени (от A до Z), ваш класс будет выглядеть следующим образом:

public class Contact implements Comparable<Contact> {

    private String name;

    // all the other attributes and methods

    public compareTo(Contact other) {
        return this.name.compareTo(other.name);
    }
}

Ответ 6

Используя lambdaj, вы можете сортировать коллекцию своих контактов (например, по их имени), как следует

sort(contacts, on(Contact.class).getName());

или по их адресу:

sort(contacts, on(Contacts.class).getAddress());

и т.д. В целом, он предлагает DSL для доступа и управления вашими коллекциями разными способами, такими как фильтрация или группировка контактов на основе некоторых условий, объединение некоторых из их значений свойств и т.д.

Ответ 7

The Collections.sort - это хорошая реализация сортировки. Если у вас нет сопоставимых для Contact контактов, вам необходимо передать реализация Comparator

Примечание:

Алгоритм сортировки представляет собой модифицированную систему слияния (в которой слияние опущено, если наивысший элемент в нижней подсписке меньше наименьшего элемента в высоком подсписке). Этот алгоритм обеспечивает гарантированную производительность n log (n). Указанный список должен быть модифицируемым, но его нельзя изменять. Эта реализация выгружает указанный список в массив, сортирует массив и выполняет итерацию по списку, сбросив каждый элемент из соответствующей позиции в массиве. Это позволяет избежать производительности n2 log (n), которая возникла бы при попытке сортировать связанный список на месте.

Сорт слияния, вероятно, лучше, чем большинство алгоритмов поиска, которые вы можете сделать.

Ответ 8

Я сделал это следующим образом. номер и имя - два arraylist. Мне нужно сортировать имя. Если какое-либо изменение произошло, чтобы называть порядок arralist, тогда числовой атрибут также изменит его порядок.

public void sortval(){

        String tempname="",tempnum="";

         if (name.size()>1) // check if the number of orders is larger than 1
            {
                for (int x=0; x<name.size(); x++) // bubble sort outer loop
                {
                    for (int i=0; i < name.size()-x-1; i++) {
                        if (name.get(i).compareTo(name.get(i+1)) > 0)
                        {

                            tempname = name.get(i);

                            tempnum=number.get(i);


                           name.set(i,name.get(i+1) );
                           name.set(i+1, tempname);

                            number.set(i,number.get(i+1) );
                            number.set(i+1, tempnum);


                        }
                    }
                }
            }



}

Ответ 9

Вы используете функцию Arrays.sort. Содержащиеся классы должны реализовывать Comparable.