Map 排序 TreeMap 陷阱

HashMap的基于hash表的实现机制决定了他非常快的检索速度,但也定了“不能排序”的标牌,工作中如果需要排序就要使用TreeMap


TreeMap是可排序map,可对ke进行排序,那么,是不是任何我们原来使用HashMap实现的业务都能使用TreeMap进行替换排序呢?

答案是:“

原因在于,它们判断重复元素机制不同:HashMap通过hashcode和equals方法来判断重复,以决定是否加入到map中

而TreeMap则是通过排序码来决定的,也就是实现Comparator元素的compare中使用到的排序码(通常与我们的业务有关系),如果排序码相同则不加入到TreeMap中,

实际工作中,HashMap中完全可能存在这种元素,因为HashMap的实现机制并没有阻止这种排序码相同的元素加入,所以不能简单的将Hashmap替换为TreeMap以完成元素排序,下面的这个例子演示了这个错误:


public static void main(String[] args) {
        class Obj implements Comparable {
            int c;
            public Obj(int c) {
                this.c = c;
            }
            @Override
            public int compareTo(Obj o) {
                return 0;//这里隐含了排序码
            }
        }
        Map hashMap = new HashMap();
        hashMap.put(new Obj(1),new Obj(0));
        hashMap.put(new Obj(3),new Obj(0));
        hashMap.put(new Obj(5),new Obj(0));
        hashMap.put(new Obj(2),new Obj(0));
        hashMap.put(new Obj(4),new Obj(0));
        System.out.println(hashMap);//5个元素

        Map treeMap = new TreeMap();
        treeMap.putAll(hashMap);
        System.out.println(treeMap);//1个元素
    }

上面的代码演示出:原先hashmap中的5个元素,被导入到treemap中后变成了1个,慎重!

所以千万不要直接将hashmap想当然地替换为treemap,你最好评估下是否会产生这种问题。

hashmap排序解决方案:

将hashmap的entry放入到list中,对list排序就好了,实例代码:

public static void main(String[] args) {
        class Obj implements Comparable {
            int c;

            public Obj(int c) {
                this.c = c;
            }

            @Override
            public int compareTo(Obj o) {
                return 0;//这里隐含了排序码
            }
        }
        Map hashMap = new HashMap();
        hashMap.put(new Obj(1), new Obj(0));
        hashMap.put(new Obj(3), new Obj(0));
        hashMap.put(new Obj(5), new Obj(0));
        hashMap.put(new Obj(2), new Obj(0));
        hashMap.put(new Obj(4), new Obj(0));
        System.out.println(hashMap);//5个元素

        List> list = new ArrayList>();
        list.addAll(hashMap.entrySet());
        Collections.sort(list, new Comparator>() {
            @Override
            public int compare(Map.Entry o1, Map.Entry o2) {
                return o1.getKey().c - o2.getKey().c;
            }
        });
        for (Map.Entry entry : list) {
            System.out.println(entry.getKey().c);
        }
    }


你可能感兴趣的:(J2SE)