2017-05-23 98 views
3

我有一个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); 
    } 
} 

谢谢。

+5

奇怪,我从来没有见过错误*莫名其妙;-) – domsson

回答

5

数组没有自然排序(即它们没有实现接口),这就是为什么当使用无参数构造函数实例化TreeMap时,代码会抛出异常。

您必须向TreeMap构造函数提供Comparator<Integer[]>以便自己定义顺序。

BTW,使用数组作为在HashMap键是一个坏主意(因为数组没有覆盖的equals()hashCode()默认实现),所以它是你切换到TreeMap一件好事。

+2

没错。否则,你会得到'在线程中的异常“main”java.lang.ClassCastException:[Ljava.lang.Integer;不能转换为java.lang.Comparable' – vikingsteve

+0

是的,这是我得到的异常。谢谢。 – Vic

+0

@Vic这是一种重要的信息,你知道;) – AxelH

1

数组没有自然排序。解决这个问题的方法之一就是做这样的事情:

TreeMap<Integer[], Integer> tm = new TreeMap<>((a1, a2) -> Integer.compare(a1[0], a2[0])); 

这会比较每个数组的第一个元素。如果数组可以为空,则需要稍微修改它,以免引发异常。

2

这可能在语法上是正确的,但它不实用。 该映射使用equals()方法确定2个键是否相等。 数组继承自Object类的方法继承equals()hashcode()方法。因此,当您要搜索特定键(数组对象)时,除非传递初始数组对象的引用,否则不会找到它。 例如

Integer arr1[] = {9, 0, 3}; 

Integer arr1_copy[] = {9, 0, 3}; 

2个不同的对象和默认equals()将失败。

但是,如果您需要使用数组作为键,您可以改为创建一个具有数组的类,因为它是成员并覆盖此类的hashcode()equals()方法并将此类用作键。

+0

这不是回答排序问题;) – AxelH

+0

好吧,一旦你“_创建一个类的数组,因为它的member_”,这个问题将来得真快;) – AxelH

+0

@AxelH你是对的 – theLearner

1

这些密钥由散列码标识。这意味着表示数组的Array对象的哈希码,而不是数组的实际内容。

这很可能不是您想到的,即使它可能适用于您正在处理的场景。

如果您认为通过移动数组中的元素,您将改变哈希映射的值桶中项目的排序,但您却错误地认为它是错误的。

1

您应该在树形图中为您提供排序首选项的比较器。

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