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

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

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

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

107 голосов | спросил Sameera0 29 72009vEurope/Moscow11bEurope/MoscowSun, 29 Nov 2009 02:18:11 +0300 2009, 02:18:11

9 ответов


0

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

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


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

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 во время сортировки)

ответил BalusC 29 72009vEurope/Moscow11bEurope/MoscowSun, 29 Nov 2009 02:25:32 +0300 2009, 02:25:32
0

В дополнение к тому, что уже было опубликовано, вы должны знать, что начиная с 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).
ответил Pshemo 6 Maypm16 2016, 19:53:16
0

Эта страница рассказывает все, что вам нужно знать о сортировке коллекций, таких как 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;
        }
        ...
    }
}
ответил bguiz 29 72009vEurope/Moscow11bEurope/MoscowSun, 29 Nov 2009 02:35:11 +0300 2009, 02:35:11
0

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

Я просто хочу добавить, что в Google-коллекциях есть .html" rel =" nofollow noreferrer "title =" com.google.common.collect.Ordering javadoc "> Класс упорядочивания , который является более" мощным ", чем стандартные компараторы. Возможно, стоит проверить. Вы можете делать классные вещи, такие как составление Порядков, их изменение, упорядочивание в зависимости от результата функции для ваших объектов ...

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

ответил Etienne Neveu 29 72009vEurope/Moscow11bEurope/MoscowSun, 29 Nov 2009 03:18:42 +0300 2009, 03:18:42
0

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

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

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);
    }
}
ответил Kaleb Brasee 29 72009vEurope/Moscow11bEurope/MoscowSun, 29 Nov 2009 02:27:40 +0300 2009, 02:27:40
0

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

Примечание:

  

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

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

ответил Joshua 29 72009vEurope/Moscow11bEurope/MoscowSun, 29 Nov 2009 02:21:32 +0300 2009, 02:21:32
0

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

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


                        }
                    }
                }
            }



}
ответил sarath 24 AM000000100000000631 2012, 10:10:06
0

используйте этот метод:

private ArrayList<myClass> sortList(ArrayList<myClass> list) {
    if (list != null && list.size() > 1) {
        Collections.sort(list, new Comparator<myClass>() {
            public int compare(myClass o1, myClass o2) {
                if (o1.getsortnumber() == o2.getsortnumber()) return 0;
                return o1.getsortnumber() < o2.getsortnumber() ? 1 : -1;
            }
        });
    }
    return list;
}

`

и используйте: mySortedlist = sortList(myList); Нет необходимости внедрять компаратор в вашем классе. Если вы хотите поменять местами в обратном порядке 1 и -1

ответил Bruno Mulas 9 52018vEurope/Moscow11bEurope/MoscowFri, 09 Nov 2018 19:41:32 +0300 2018, 19:41:32
0

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

ответил monksy 29 72009vEurope/Moscow11bEurope/MoscowSun, 29 Nov 2009 02:20:40 +0300 2009, 02:20:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132