while(entrySetIterator.hasNext()){
Entry
System.out.println(entry.getValue());
}
System.out.println("entryset遍历时间---------------------------:"+(System.currentTimeMillis()-startTimeTwo));
}
}
public class HashMapTest {
public static void main(String[] args) {
HashMap
HashMap
for (int i= 0;i<1000;i++) {
keySetMap.put(""+i, "keySet");
}
for(int i=0;i<1000;i++){
entrySetMap.put(""+i,"entrySet");
}
long startTimeOne = System.currentTimeMillis();
Iterator
while (keySetIterator.hasNext()) {
System.out.println(keySetMap.get(keySetIterator.next()));
}
System.out.println("keyset遍历时间-------------------------------:"+(System.currentTimeMillis()-startTimeOne));
long startTimeTwo=System.currentTimeMillis();
Iterator
while(entrySetIterator.hasNext()){
Entry
System.out.println(entry.getValue());
}
System.out.println("entryset遍历时间---------------------------:"+(System.currentTimeMillis()-startTimeTwo));
}
}
通过多次运行测试发现,entryset遍历时间比keyset遍历时间短许多,entryset方式的性能通常要比keyset方式高一倍。
三。原因何在?
通过查看源代码发现,调用keySetMap.keySet()这个方法会生成keyIterator迭代器,
其next()方法只返回其key值,然后再通过key值在keySetMap中获得其value值,代码如:keySetMap.get(keySetIterator.next())
而调用entrySetMap.entrySet()方法会生成EntryIterator迭代器,其next()方法返回一个Entry对象的一个实例,其中包含key值和value值。
如果遍历HashMap时只取其key值,那么两种方式的遍历在性能上应该是相同的。
但同时取key值和value值时,keyset方式比entryset方式多遍历了一次table,此时keyset方式性能差些。
hashMap深度分析(转载)
java.util.HashMap是很常见的类,前段时间公司系统由于对HashMap使用不当,导致cpu百分之百,
在并发环境下使用HashMap 而没有做同步,可能会引起死循环,关于这一点,sun的官方网站上已有阐述,这并非是bug。
HashMap的数据结构
HashMap主要是用数组来存储数据的,我们都知道它会对key进行哈希运算,哈系运算会有重复的哈希值,对于哈希值的冲突,HashMap采用链表来解决的。
在HashMap里有这样的一句属性声明:
transient Entry[] table;
Entry就是HashMap存储数据所用的类,它拥有的属性如下
final K key;
V value;
final int hash;
Entry
看到next了吗?next就是为了哈希冲突而存在的。
比如通过哈希运算,一个新元素应该在数组的第10个位置,但是第10个位置已经有Entry,那么好吧,
将新加的元素也放到第10个位置,将第10个位置的原有Entry赋值给当前新加的 Entry的next属性。
数组存储的是链表,链表是为了解决哈希冲突的,这一点要注意。
几个关键的属性
存储数据的数组
transient Entry[] table; 这个上面已经讲到了
默认容量
static final int DEFAULT_INITIAL_CAPACITY = 16;
最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;
默认加载因子,加载因子是一个比例,当HashMap的数据大小>=容量*加载因子时,HashMap会将容量扩容
static final float DEFAULT_LOAD_FACTOR = 0.75f;
当实际数据大小超过threshold时,HashMap会将容量扩容,threshold=容量*加载因子
int threshold;
加载因子
final float loadFactor;
HashMap的初始过程
构造函数1:
[java]
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +