HashSet及LinkedHashSet源码分析(…

来源:互联网 发布:广东网络干部培训补考 编辑:程序博客网 时间:2024/04/27 14:07

    Java容器类的用途是“保存对象”,分为两类:Map——存储“键值对”组成的对象;Collection——存储独立元素。Collection又可以分为List和Set两大块。List保持元素的顺序,而Set不能有重复的元素。

    本文分析Set中最常用的HashSet类,并简单介绍和对比LinkedHashSet。

    首先对Set接口进行简要的说明。 

    存入Set的每个元素必须是惟一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set不保证维护元素的次序。Set与Collection有完全一样的接口。

    在没有其他限制的情况下需要Set时应尽量使用HashSet,因为它对速度进行了优化。

    下面是HashSet的定义: 

1 public class HashSet2     extends AbstractSet3     implements Set, Cloneable, java.io.Serializable

    HashSet继承了AbstractSet,实现了Set接口。其实AbstractSet已经实现Set接口了。AbstractSet继承自AbstractCollection,而AbstractCollection实现了Collection接口的部分方法,而Set接口和Collection接口完全一致,所以AbstractSet只是实现了AbstractCollection没有实现的Set接口的方法和重写了部分AbstractCollection已经实现的方法。

    下面是HashSet定义的属性:

1 private transient HashMap map;2 private static final Object PRESENT = new Object();

    为什么会有一个HashMap定义的属性?

    想一下HashMap有什么特点:基于哈希表,存储键值对,Key不能相同等等。Key不能相同!这个特点是不是和Set的元素不能相同和类似?如果将Set的元素当成Map的Key,是否就保证了元素的不重复?!答案是肯定的。但是Map存储键值对,Key有了,那么Value呢?这正是第二个属性PERSENT的意义。看到PERSENT属性时一个Object对象,且是static和final的,它的用途就是当做Value存进map中。

    总结一下,HashSet的实现方式大致如下,通过一个HashMap存储元素,元素是存放在HashMap的Key中,而Value统一使用一个Object对象。

    这样看来HashSet应该很简单,应该只是使用了HashMap的部分内容来实现。

    下面看具体的其它代码来验证上面的猜想。

    构造方法:

复制代码
 1 // 构造方法一:调用默认的HashMap构造方法初始化map 2 public HashSet() { 3     map = new HashMap(); 4 } 5 // 构造方法二:根据给定的Collection参数调用HashMap(int initialCapacity)的构造方法创建一个HashMap(这个构造方法的HashMap的源码分析里已经描述过了) 6 // 调用addAll方法将c中的元素添加到HashSet对象中 7 public HashSet(Collection