我有一个对象的ArrayList(POJO),它有一个Id和另一个字段。我已经在Id字段的POJO中实现了equals()/ hashcode()覆盖。当我使用Object类的equals()方法比较两个对象时,它完全正常。但是,当我将这些对象添加到arraylist并实现
时Collections.sort(arrListOfObjects);
它给了我一个classCastexception。我抬起头,发现我需要实现一个比较器。这个比较器也做了等于/ hashcode覆盖的东西。如果是这样那么为什么上面的代码不起作用?(我知道没有比较器,但我的问题是,是否不可能基于对象的哈希码实现排序?)
答案 0 :(得分:6)
如消息所示,您的对象需要实现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());
}
}
答案 1 :(得分:0)
Comparator不对equals或hashcode做任何事情,它使用equals或hashcode来确定它返回的内容。它是Collections.sort方法文档的一部分。看看吧 Comparable接口并在您的课程中实现它。您可以查看SO问题java class implements comparable作为示例。
答案 2 :(得分:0)
实现基于哈希代码的排序当然是可能的,但可能不会始终如一地产生所需的行为。例如,考虑一个类Foo
,其hashCode()
方法被定义为始终返回一个常量值。例如:
public int hashCode() {
return 1;
}
鉴于这个hashCode方法与使用此方法定义的Comparator串联,几乎可以肯定列表无法正确排序,除非有琐碎的情况(空列表,单个元素列表等)。
一般来说,要记住的一件好事是java.lang.Object.hashCode java doc中记录的hashCode-equals契约。简而言之,hashCode碰撞可能会导致不对等的对象,使得在这些方法上定义的排序无效。
答案 3 :(得分:0)
随着Java8或更高版本的出现,我将使用lambda表达式实现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()));
}
答案 4 :(得分:0)
如果使用Java 8,则可以通过以下方式进行定义:
list.stream().sorted(Comparator.comparing(Pojo::hashCode));
此方法不需要Pojo实现Comparable
接口。