简体   繁体   中英

Sorting ArrayList of Objects using Hashcode

I have an ArrayList of Objects(POJOs) that have an Id and another field. I have implemented the equals()/hashcode() override in the POJO for the Id field. When I compare two objects using the equals() method of the Object class, it works perfectly fine. However when I add these objects to an arraylist and implement the

Collections.sort(arrListOfObjects);

it gives me a classCastexception. I looked up and found that I need to implement a Comparator. This comparator also does something to equals/hashcode override. If that is so then why does the above code not work?(I know that there is no comparator, but my question is, is it not possible to implement a sort based on the hashcode of the object?)

As the message says, your object needs to implement the Comparable interface to be sortable. Alternatively, you can provide a comparator to your sort() method. For example, assuming your objects are Strings and you want to sort based on hashcodes, you could do this:

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

With Java8 or higher being around I would implement the Comparator using a lambda expression;

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

If java 8 is an option you can define it this way:

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

This approach does not require the Pojo to implement Comparable interface.

Comparator does not do anything to equals or hashcode, it uses equals or hashcode to determine what it returns. It is part of the documentation for the Collections.sort method. Take at look at at Comparable interface and implement it in your class. You can take a look at the SO Question java class implements comparable for an example.

Implementing a sort based on a hash code is certainly possible, but might not consistently produce the behavior desired. For instance, consider a class Foo whose hashCode() method is defined to always return a constant value. For example:

public int hashCode() {
     return 1;
}

Given this hashCode method in tandem with a defined Comparator using this method, lists are almost certain to not be sorted correctly, barring the trivial cases (empty list, single element list, etc.).

In general, a good thing to bear in mind is the hashCode-equals contract documented in the java.lang.Object.hashCode java doc. In a nutshell, it is possible hashCode collisions may result for unequal objects, rendering sorts defined on those methods ineffective.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM