HashMap简述
在JDK中,HashMap是存储键值对用的比较多的一个类。
其基于哈希散列表计算位置来达到键不重复存储。
其内部数据结构是数组(散列桶)+链表+红黑树,
数组是基础存储,存储位置为计算出来的hash值和数组长度减一相与,而数组长度一直都为2的整数幂。
链表是遇到哈希碰撞时,即数组同一下标要存放第二个值的时候,会在原值后面链接上下一个键值对。
红黑树是在链表过长(默认大于8)时进行的结构重组,将链表转换为红黑树,加快搜索效率。
HashMap的声明
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
扩展Map接口代表这个类是存储键值对的数据结构。
HashMap的域
在以往的版本中,是用Entry<K,V>来表示一个键值对结点的,而后来引入了红黑树表示的节点(TreeNode),就产生了新的表示方法(Node)。
Node
fields
HashMap的构造方法
constructors
除了参数为Map的构造方法,其余的都是参数检测和默认赋值,
另外值得一提的是,传入initCapacity的构造方法都会先将其放入threshold中,
可以发现构造方法中并没有构建任何数据结构,这些会在第一次put中才会生成。
参数为Map的构造方法调用了另外的核心方法,后面再详细叙述。
HashMap的关键方法
介绍增删改查之前,先介绍有关size的方法,也就是table大小的设定。
resize方法除了初始化会使用,在扩容的时候也会使用,但也同样保证了是2次幂。
size
put
putAll
get
remove
clear
在JDK1.8中还增加了一些关于“默认值“和”指定值”增删改查的功能,在这里不再详细分析,
只给出方法签名和用处,代码本身也比较简单,感兴趣的可以自己去了解一下。
jdk1.8
HashMap的遍历
Map和LIst不同,因为Map有两个泛型参数,所以进行遍历的时候一个迭代器不能满足所有迭代需求,
熟悉HashMap的同学应该知道,JDK提供了3个便于我们访问的方法,而其返回的对应是3个集合。
这3个方法是values(),keySet(),EntrySet()。
从命名和Map我们都可以知道,后两个是不能重复的Set,而第一个只是Collection,
更值得一提的是,他们都是HashMap的内部类,在这里只用EntrySet()来举例,其他两个都差不多甚至更简单。
entrySet
可能有的同学会问了,为什么不用Node<K,V>而要用Entry<K,V>呢,搞的还要转换。
因为之前版本都是用的Entry,突然改成Node会使很多代码要重写,不太合适,而且Entry在遍历的时候已经足够使用。
遍历的时候仍是采取了迭代器的方式。
EntryIterator
可以发现,EntrySet的迭代器和HashMap中数据内容是息息相关的,
也就是说是互相影响的,这也是HashMap不能在多线程使用的原因之一。
http://www.cnblogs.com/bhbcsc/p/7143141.html