你的位置:首页 > Java教程

[Java教程]关于hashmap的排序


刚学java不久

之前在学习hashmap的时候

无意间发现,诶?怎么结果是排序的,然后重新输入了好多次,握草,原来java 1.8都实现了hashmap的排序

天真的我没有去网上查,没有去想java collections的框架,就本真的想,hashmap真厉害

要不是今天无意间翻起,可能之后会一直按照它是排序的来用......

首先从框架角度,它是继承自abstractmap,实现了map,Cloneable, Serializable等接口,显然本身是不会对数据排序

然后在看过源码之后,这个是put调用的代码,

 1 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, 2          boolean evict) { 3     Node<K,V>[] tab; Node<K,V> p; int n, i; 4     if ((tab = table) == null || (n = tab.length) == 0) 5       n = (tab = resize()).length; 6     if ((p = tab[i = (n - 1) & hash]) == null)//根据hash值判断是否可以直接插入 7       tab[i] = newNode(hash, key, value, null); 8     else {//如果已经有对象在此存放 9       Node<K,V> e; K k;10       if (p.hash == hash &&11         ((k = p.key) == key || (key != null && key.equals(k)))) //如果插入key与原来的key相同,当然hash值也相同,覆盖12         e = p;13       else if (p instanceof TreeNode)14         e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);15       else {  //key不同,但是hash值相同的对象16         for (int binCount = 0; ; ++binCount) {17           if ((e = p.next) == null) {18             p.next = newNode(hash, key, value, null);19             if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st20               treeifyBin(tab, hash);21             break;22           }23           if (e.hash == hash &&24             ((k = e.key) == key || (key != null && key.equals(k))))25             break;26           p = e;27         }28       }29       if (e != null) { // existing mapping for key30         V oldValue = e.value;31         if (!onlyIfAbsent || oldValue == null)32           e.value = value;33         afterNodeAccess(e);34         return oldValue;35       }36     }37     ++modCount;38     if (++size > threshold)39       resize();40     afterNodeInsertion(evict);41     return null;42   }

对代码看的不太仔细,但是肯定是没有排序代码的

然后想了想自己之前为什么会误以为排序的呢

看数据

1 HashMap hm = new HashMap();2     hm.put(5, "five");3     hm.put(4, "one");4     hm.put(1, "two");5     hm.put(6, "zero");

View Code

......

然后再联想put的代码,然后hash的代码

1 public V put(K key, V value) {2   return putVal(hash(key), key, value, false, true);3 }

1 static final int hash(Object key) {2     int h;3     return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);4   }

hashcode方法的代码,对应于每一个类,实现不同,这儿就用Integer

1 public int hashCode() {2     return Integer.hashCode(value);3   }4 5  6 public static int hashCode(int value) {7     return value;8   }

可以看到,直接返回int值

然后hash函数内,假设key!=null,那么返回值就等于h^(h>>>16)       //这个>>>的意思应该是h/(Math.pow(2,16))

那么,返回值就是 h与h/65536的异或了

所以,在integer对象为key的情况下,只要输入值小于65536,hash值都是integer本身数值,而hash值对应于table数组中的位置

所以在table数组中,是排序的……

 

当然,hashmap也是可以排序的

将它的entryset加入list对象

然后调用collections.sort即可,不过需要重写sort方法,代码如下(网上查的),hm是hashmap对象

 1 //实现排序/*5*/ 2     /*List<Map.Entry<Integer, String>> lt = new ArrayList<Entry<Integer, String>>(hm.entrySet()); 3     System.out.println(lt.get(0)); 4     Collections.sort(lt, new Comparator<Map.Entry<Integer, String>>() 5     { 6       @Override 7       public int compare(Map.Entry<Integer,String> o1, Map.Entry<Integer,String> o2) {    8         //return (o2.getValue() - o1.getValue());  9         return (o1.getKey()).compareTo(o2.getKey());10       }  11     });*/

 

 

 

还有

看hash函数的时候,也验证了,hashmap的key值是允许为空的,默认当作0来处理

区别于hashtable

 

 

有点乱……

不过想想是自己的第一篇博客,满意了

加油