hashMap 怎么说呢。 我的理解是 外表是一个set 数组,无序不重复 。 每个set元素是一个bean ,存着一对key value

看看代码吧

package test;

import java.util.HashMap;
import java.util.Map.Entry; public class HashMaptest { public static void main(String[] args) { HashMap<String, String> map = new HashMap<String, String>(); String aa = "张三";
String bb = "李四";
map.put(aa, "22");
map.put(bb, "34234");
map.put("张三", "223"); System.out.println(aa.hashCode());
System.out.println(bb.hashCode()); for (Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey()); // System.out.println(entry.getValue());
} } }

打印的结果是:


李四
张三

可以看到, 虽然张三是先插进去的, 但是确在后面打印出来,说明这个数组不是有序的, 不是list;

虽然aa  的 hashcode=774889 大于bb 的, 肯定不是根据大小插入的,应该是把 得到的hashcode 取余 , 例如  6%7 = 6 , 9%(7+1)=1 ,6>1  ,所以9 在前面,这里为什么是  第一个除以7 ,第二个进来确实% 8呢;

因为hash算法是 这样的:

int hash = key.hashCode(); // 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值
int index
= hash % Entry[].length;
Entry[index] = value;

这里看到  Entry[].length 一直在增加的;

所以就会遇到hash冲突, 总有碰到取余后一样的;

好了,举个例子:

比如 key="张三", hashcode=666 ,entry的size是 100   666%100=66  ;存在  66 位置上。  这个时候 key="李四" 要插入了, hashcode =6666 entry的size是 6600  6666%6600=66 , 这样 66 位置就hash冲突了;

这里和我代码写的覆盖不是一回事 。 代码的 key  相同,这里在特别说明下:可能有人说, 两个张三的hashcode 一样, 不同时候插入,entry 的 size不是不一样吗, 那就不会覆盖了? 这么想是错误的, 其实 map 插入的时候是先比较equals  的, 发现,咦 ,相同, 直接覆盖原值

:附上 hashMap的Put 方法源码:

   final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}

可能比较难懂, 主要在这句:

if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }

已存在的key ,之而立是直接覆盖的。

最新文章

  1. CentOS7中安装MySQL(简便)及 网站的搭建
  2. Linux操作系统安装JDK
  3. HttpURLConnection网络请求
  4. 破解Mysql数据库密码
  5. RMQ (Range Minimal Query) 问题 ,稀疏表 ST
  6. JVM参数汇总
  7. 常见的Unix指令
  8. Summary of Amazon Marketplace Web Service
  9. 段落排版--缩进(text-indent)
  10. javascript 中的nextSibling和previousSibling使用注意事项
  11. WPF换肤之三:WPF中的WndProc
  12. javascript常用知识点集
  13. 简单轻量级的一套JS 类库(RapidDevelopmentFramework.JS)
  14. 朱世杰恒等式的应用-以CF841C为例
  15. Asp.net常用开发方法之DataTable/DataReader转Json格式代码
  16. 数据结构-快速排序(C#实现)
  17. springboot 使用Filter
  18. PAT A1103
  19. Light OJ 1095
  20. ftp修改上传后目录、文件权限问题 aix

热门文章

  1. HDU-1501-Zipper-字符串的dfs
  2. 新增加的html里的标签元素,该元素作为事件,js获取不到id的问题
  3. 2_1.springboot2.x配置之配置文件解析
  4. 12_springmvc拦截器
  5. js input框限制输入为数字并限制长度
  6. c语言排序代码实现
  7. Crontab- Linux必学的60个命令
  8. NBIS指纹特征提取与匹配软件使用
  9. $.ajax()方法和$.get()方法使用小结
  10. VS2010版的Speex音频处理模块(附源码+测试demo)