我有HashMap<Float[], Integer>
,我可能需要将其转换为TreeMap
。如何对TreeMap的键(即数组)进行排序?通过他们的第一个元素?
我打算进行一项简单的测试,但却以某种方式导致了错误:
public class treeMapTest {
public static void main(String[] args) {
Integer arr1[] = {9, 0, 3};
Integer arr2[] = {2, 2, 2};
Integer arr3[] = {4, 2, 1};
TreeMap<Integer[], Integer> tm = new TreeMap<Integer[], Integer>();
tm.put(arr1, 7);
tm.put(arr2, 7);
tm.put(arr3, 7);
System.out.println(tm);
}
}
谢谢。
答案 0 :(得分:5)
数组没有自然排序(即它们没有实现Comparable
接口),这就是为什么当使用无参数实例化TreeMap
时代码会引发异常的原因构造
您必须向Comparator<Integer[]>
构造函数提供TreeMap
才能自行定义订单。
BTW,在HashMap
中使用数组作为键是一个坏主意(因为数组不会覆盖equals()
和hashCode()
的默认实现),所以&#39你切换到TreeMap
是一件好事。
答案 1 :(得分:2)
这可能在语法上是正确的,但它实际上并不实用。
地图使用equals()
方法确定2个密钥是否相等。
数组从Object类继承equals()
和hashcode()
方法。因此,当您要搜索特定键(数组对象)时,除非传递初始数组对象的引用,否则您将无法找到它。
例如,
Integer arr1[] = {9, 0, 3};
和
Integer arr1_copy[] = {9, 0, 3};
是2个不同的对象,默认equals()
将失败。
但是,如果你需要使用数组作为键,你可以做的是创建一个带有数组的类作为它的成员并覆盖此类的hashcode()
和equals()
方法并使用此类作为密钥。
答案 2 :(得分:1)
数组没有自然顺序。解决问题并使其可预测的一种方法是做这样的事情:
TreeMap<Integer[], Integer> tm = new TreeMap<>((a1, a2) -> Integer.compare(a1[0], a2[0]) );
这将比较每个数组的第一个元素。如果数组可以为空,则需要稍微更改一下,这样就不会引发异常。
答案 3 :(得分:1)
密钥由哈希码识别。这意味着表示数组的Array对象的哈希码,而不是数组的实际内容。
这很可能不是你想到的,即使它可能适用于你正在处理的场景。
如果您认为通过在数组中移动元素,您将要更改哈希映射的值存储区中项目的排序,那么您会感到非常错误。
答案 4 :(得分:1)
您应该在Treemap中为您提供排序首选项的Comparator。
public static void main(String[] args) {
Integer arr1[] = {9, 0, 3};
Integer arr2[] = {2, 2, 2};
Integer arr3[] = {4, 2, 1};
TreeMap<Integer[], Integer> tm = new TreeMap<Integer[], Integer>(new Comparator<Integer[]>() {
@Override
public int compare(Integer[] o1, Integer[] o2) {
int cmp=o1[0].compareTo(o2[0]);
return cmp;
}
});
tm.put(arr1, 7);
tm.put(arr2, 7);
tm.put(arr3, 7);
for(Integer[] o1:tm.keySet())
System.out.println(o1[0]);
}