Сортировка ArrayList объектов с использованием хэш-кода - PullRequest
4 голосов
/ 14 марта 2012

У меня есть ArrayList объектов (POJO), у которых есть Id и другое поле. Я реализовал переопределение equals () / hashcode () в POJO для поля Id. Когда я сравниваю два объекта с помощью метода equals () класса Object, он работает отлично. Однако, когда я добавляю эти объекты в массив и реализую

Collections.sort(arrListOfObjects);

это дает мне classCastexception. Я посмотрел вверх и обнаружил, что мне нужно реализовать Comparator. Этот компаратор также делает что-то для переопределения equals / hashcode. Если это так, то почему вышеприведенный код не работает? (Я знаю, что нет компаратора, но мой вопрос: нельзя ли реализовать сортировку на основе хеш-кода объекта?)

Ответы [ 5 ]

6 голосов
/ 14 марта 2012

Как говорится в сообщении, ваш объект должен реализовывать интерфейс Comparable для сортировки. Кроме того, вы можете предоставить компаратор для вашего sort() метода. Например, предполагая, что ваши объекты являются строками, и вы хотите сортировать по хеш-кодам, вы можете сделать это:

public static void main(String[] args) {
    List<String> list = Arrays.asList("string", "sdkj");
    for (String s : list) {
        System.out.println(s + "=" + s.hashCode());
    }
    Collections.sort(list, new Comparator<String>() {

        @Override
        public int compare(String o1, String o2) {
            return o1.hashCode() - o2.hashCode();
        }
    });
    System.out.println("After Sorting");
    for (String s : list) {
        System.out.println(s + "=" + s.hashCode());
    }
}
0 голосов
/ 25 октября 2018

Если java 8 является опцией, вы можете определить ее следующим образом:

list.stream().sorted(Comparator.comparing(Pojo::hashCode));

Этот подход не требует от Pojo реализации интерфейса Comparable.

0 голосов
/ 25 октября 2018

При наличии Java8 или выше я бы реализовал Comparator с помощью лямбда-выражения;

public static void main(String[] args) {
    List<String> list = Arrays.asList("string", "sdkj");
    list.forEach(s -> System.out.println(s + "=" + s.hashCode()));

    Collections.sort(list, (o1, o2) -> (o1.hashCode() - o2.hashCode()));

    System.out.println("After Sorting");

    list.forEach(s -> System.out.println(s + "=" + s.hashCode()));
}
0 голосов
/ 14 марта 2012

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

public int hashCode() {
     return 1;
}

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

В общем, следует помнить о контракте hashCode-equals, задокументированном в java.lang.Object.hashCode java doc. В двух словах, возможно, что коллизии hashCode могут привести к неравным объектам, что сделает неэффективными определенные им методы.

0 голосов
/ 14 марта 2012

Comparator не делает ничего для равенства или хэш-кода, он использует равенства или хэш-код для определения того, что он возвращает. Он является частью документации для метода Collections.sort . Взгляни на Сопоставим интерфейс и реализуем его в своем классе. Вы можете взглянуть на SO Question java-класс реализует сопоставимый для примера.

...