关于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 1st
20                             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 key
30                 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

 

 

有点乱……

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

加油

 

posted @ 2016-05-22 15:56  hyhappy  阅读(1952)  评论(0编辑  收藏  举报