问题描述
public class test {
public static void main(String[] args) {
Map<Object,Object> m = new TreeMap();
m.put("1",new ArrayList());
m.put(1,new Object());
m.put(1.0,"Hello");
System.out.println(m);
}
}
Exception in thread "main" java.lang.classCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap')
at java.base/java.lang.Integer.compareto(Integer.java:64)
at java.base/java.util.TreeMap.put(TreeMap.java:566)
at test.main(test.java:8)
但这不会发生在 HashMap
并且编译成功。我想知道这怎么可能?
解决方法
TreeMap
在内部使用比较器来构建红黑树。在这种情况下,您没有提供它,因此它会尝试比较 Integer
和 String
,它们彼此不可比较。例如,您可以提供这样的比较器:
Map<Object,Object> m = new TreeMap<>(Comparator.comparing(String::valueOf));
m.put("1",new ArrayList<>());
m.put(1,new Object());
m.put(1.0,"Hello");
System.out.println(m);
输出:
{1=java.lang.Object@3fee733d,1.0=Hello}
根据此比较器,前两个元素是相同的,元素 new Object()
使用实现的默认 toString
方法。
HashMap
在内部使用 hashCode
方法来构建哈希表。该方法至少在 Object
类中实现,并被派生类覆盖:String
、Integer
和 Double
。这就是为什么这段代码工作正常:
Map<Object,Object> m = new HashMap<>();
m.put("1","Hello");
System.out.println(m);
输出:
{1.0=Hello,1=[],1=java.lang.Object@5451c3a8}