【问题标题】:java.lang.ClassCastException: List cannot be cast to java.lang.Comparable [duplicate]java.lang.ClassCastException:列表无法转换为 java.lang.Comparable [重复]
【发布时间】:2015-10-27 04:35:39
【问题描述】:

我需要将两个相同类型的对象列表添加到一个 SET 中。我应该确保集合的顺序是自然顺序,并且在 SET 中没有没有修复

我阅读了this question 的答案,但没有帮助。

例如我的输入和输出应该如下

列表 1

A A1 List1
B B1 List1
B B1 List1

清单 2

C C1 List2
D D1 List2
A A1 List2

输出

List1
A A1
B B1
List2
C C1
D D1

如您所见,输出的List 1 中不存在第二个B B1,因为list 1 上有两个B B1

同样A A1 不存在于输出的list 2 中,因为它已存在于输出的List 1 中。

还保留每个列表的顺序。 (首先添加列表 1,因此列表 1 位于列表顶部,之后列表 2 并保留其所有元素的顺序。)

public class MyList{
    private String name;
    private String code;
    private String group;

    //setters and getters
}

List<MyList> list1 = new ArrayList<MyList>();
List<MyList> list2 = new ArrayList<MyList>();
....
Set<MyList> output = new TreeSet<MyList>();
output.addAll(list1);
output.addAll(list2);

抛出的异常

java.lang.ClassCastException: com.myproject.MyList cannot be cast to java.lang.Comparable
    at java.util.TreeMap.compare(TreeMap.java:1290)
    at java.util.TreeMap.put(TreeMap.java:538)
    at java.util.TreeSet.add(TreeSet.java:255)
    at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
    at java.util.TreeSet.addAll(TreeSet.java:312)

为了解决这个问题,我将 Comparable 添加到 MyList 类,但它改变了 SET 的顺序。如何保持 SET 的自然顺序?

【问题讨论】:

  • 自然秩序是什么意思?
  • @Codebender 我的意思是它们被添加到集合中的顺序。请查看我在问题中的示例输出列表。
  • 好吧,你上面提供的数据结构不是一个列表……不知道为什么你一直把它称为一个列表。提供“列表”的完整实现,显示您如何向其中添加内容
  • @Smac89 它们都是 ArrayLists,问题已更新。

标签: java arraylist set


【解决方案1】:

如果您想要一个维护插入顺序的Set,您要查找的类是LinkedHashSet

实现是一个哈希表,它还维护一个条目的链接列表,它允许您按照条目添加的顺序迭代条目。

【讨论】:

  • 就性能而言,这是最好的选择吗?
  • @Jack: LinkedHashSet 已经摊销了 O(1) 的插入和查找,迭代是 O(N)。渐近地你不会变得比这更好。但是,常数因子将略高于ArrayListHashSet,并且每个条目的内存使用量将多出几个字节。简而言之:它极不可能使您的程序变慢。与往常一样,在处理性能问题时,衡量而不是猜测。与标准库代码相比,您更有可能在自己的代码中(例如在您的 equalshashCode)中发现性能问题。
【解决方案2】:

TreeSet 的“自然顺序”由您的 MyList.class 中的 compareTo() 实现。因为 TreeSet 不知道如何为您的对象排序,但它必须这样做。 如果您需要通过“将它们添加到集合中”进行排序 - 使用 LinkedHashSet

【讨论】:

  • HashSet 绝不会保证您的订单。
  • 好的,抱歉。使用 LinkedHashSet。它根据插入顺序保留顺序。
  • @AlexeyKhamitov 是性能方面的最佳选择吗?
  • @Jack 如果你真的需要 Set - 是的,它是。 LinkedHashSet / TreeSet:添加 O(1) / O(log n) 得到 O(1) / O(log n) 包含 O(1) / O(log n) 删除 O(1) / O(log n)跨度>
【解决方案3】:

仅在名称和代码上创建等于和哈希码。你也可以做一个比较方法来保持原来的顺序。

【讨论】:

    【解决方案4】:

    如何保持SET的自然顺序?

    List 是为此而生的,不是set,Set 是无序的,但 TreeSet 只有在你定义Comparator 时才会根据指定的比较器排序。否则 TreeSet 不知道它应该以什么顺序保存对象。

    获取一个列表,它将为您提供所需的输出。

    【讨论】:

      【解决方案5】:

      如果你需要使用 TreeSet 那么你必须使用 Compartor 或 Comparable 来扩展你的类 mylist 一个 hashset 将不能保证顺序并且任何需要以除原始/包装类型以外的方式排序/排序的对象都需要显式方式告诉 JVM 如何对它们进行排序,否则 JVM 将不知道它必须对对象中的哪个属性进行排序,因此错误 java.lang.ClassCastException: com.myproject.MyList cannot be cast to java.lang.Comparable

      【讨论】:

        猜你喜欢
        • 2012-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        • 2021-07-24
        • 2017-07-07
        • 2016-12-05
        相关资源
        最近更新 更多