Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[问答]HashMap有哪些考察点? #109

Open
miao1007 opened this issue Mar 24, 2015 · 8 comments
Open

[问答]HashMap有哪些考察点? #109

miao1007 opened this issue Mar 24, 2015 · 8 comments

Comments

@miao1007
Copy link

虽然我经常用HashMap,但是我还没有真正接触过正式的面试,所以想问一下HashMap在面试时经常考察什么?

目前我已经了解到的有:

  • HashMap实现了Map接口,无同步锁;
  • HashMap按照HashCode把key-value均匀的填入数组中,如果出现冲突,就使用链地址法挂上链表遍历;

除了上面两点,还有什么可能出现的考点吗?求各位前辈赐教

@2022happynew
Copy link

个人认为hashcode和equals方法比较重要~这也是hashmap实现元素唯一的原理

@qianzui
Copy link

qianzui commented Mar 25, 2015

说到底还是对HashMap结构的理解啦!
影响HashMap性能的因素有哪些? 已知大概元素的个数的情况下如何有效的提高HashMap的性能?
如何避免Hash碰撞?如何扩容?如何实现Hash攻击?

往深了可以再问问Java8里HashMap实现的变化,有何优点,解决的问题,等等等。。。

我始终认为:只有对HashMap理解十分透彻的才能叫一个好的Java程序员!

@miao1007
Copy link
Author

自己把坑填了,楼上的问题基本解答了,如果我的回答有问题的话,请一定要指出!

####性能提高的一些方式
1.1. 减少碰撞
我们知道HashMap的时间复杂度取决于O(N//buckets),所以为了尽量少挂链表,获取hashCode的算法一定要高效;在JDK8中引入了红黑二叉树,当链表元素达到8的时候,把链表动态转成树,可以把最差时间复杂度从O(N)降到O(logN)

1.2. 选好初始容量
resize需要遍历所有的数组并重新计算Hash,所以初始容量确定了,就可以减少损失。

比如你有1000个数据 x * 0.75 = 1000 ,x = 1333,又HashMap中都是按照2^N排序的,所以应该选择2048作为初始容量。

1.3. 数据结构的选择
当数据非常多,对搜索要求高的情况下,考虑使用树。

详细的可以看: http://www.jianshu.com/p/e54047b2b563

@chenshiqiang1202
Copy link

今天看了下源码,基本结构整理了下:
链表结构:
static class HashMapEntry<K, V> implements Entry<K, V> {
final K key;
V value;
final int hash;
HashMapEntry<K, V> next;
......
}

数组存储所有链表:
transient HashMapEntry<K, V>[] table;

key的hash值的计算:
int hash = Collections.secondaryHash(key);

table中HashMapEntry位置的计算:
int index = hash & (tab.length - 1); //通过key的hash值获得

新增元素:
//放在链表的最前面,next = table[index]
table[index] = new HashMapEntry<K, V>(key, value, hash, table[index]);

取元素:
//找到key的hash对应的HashMapEntry,然后遍历链表,通过key.equals取值
for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)]; e != null; e = e.next) {
K eKey = e.key;
if (eKey == key || (e.hash == hash && key.equals(eKey))) {
return e.value;
}
​}

@joure
Copy link

joure commented Mar 29, 2015

hashcode()和equals() 方法
HashMap与HasnTable的区别

@DonLiangGit
Copy link

在面试startup的时候曾经有三次遇到Hash类编程题。

  1. 类K sum题
  2. 选择数组里重复元素的前一个元素index
  3. 订飞机票题(给定一个机票集合,求机票顺序)

@philofly
Copy link

philofly commented May 5, 2015

  1. 同步问题
  2. 多线程可以使用hashtable或者concurrentHashMap替换
  3. 初始化大小多少
  4. 超过多大空间需要扩充,扩充原则是什么
  5. 冲突如何解决

@niuxinghua
Copy link

rehash 时间复杂度

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants