Set集合与List一样,都是继承自Collection接口,常用的实现类有HashSet和TreeSet。值得注意的是,HashSet是通过HashMap来实现的而TreeSet是通过TreeMap来实现的,所以HashSet和TreeSet都没有自己的数据结构,具体可以归纳如下:
- Set集合中的元素不能重复,即元素唯一
- HashSet按元素的哈希值存储,所以是无序的,并且最多允许一个null对象
- TreeSet按元素的大小存储,所以是有序的,并且不允许null对象
- Set集合没有get方法,所以只能通过迭代器(Iterator)来遍历元素,不能随机访问
1.HashSet
下面给出HashSet的部分源码,以理解它的实现方式。
1 static final long serialVersionUID = -5024744406713321676L; 2 3 private transient HashMap<E,Object> map; 4 5 // Dummy value to associate with an Object in the backing Map 6 private static final Object PRESENT = new Object();
观察源码,我们知道HashSet的数据是存储在HashMap的实例对象map中的,并且对应于map中的key,而Object类型的引用PRESENT则是对应于map中的value的一个虚拟值,没有实际意义。联想到HashMap的一些特性:无序存储、key值唯一等等,我们就可以很自然地理解Set集合元素不能重复以及HashSet无序存储的特性了。
下面从源代码的角度来理解HashSet的基本用法:
- 构造器(四种)
1.HashSet() 空的构造器,初始化一个空的HashMap
2.HashSet(Collection<? extends E> c) 传入一个子集c,用于初始化HashMap
3.HashSet(int initialCapacity, float loadFactor) 初始化一个空的HashMap,并指定初始容量和加载因子
4.HashSet(int initialCapacity) 初始化一个空的HashMap,并指定初始容量
public HashSet() { map = new HashMap<>(); } public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); }
- 插入元素
1.add(E e) 插入指定元素(调用HashMap的put方法实现)
1 Set<String> hashSet = new HashSet<String>(); 2 hashSet.add("D"); 3 hashSet.add("B"); 4 hashSet.add("C"); 5 hashSet.add("A");
- 查找元素
1.contains(Object o) 判断集合中是否包含指定的元素(调用HashMap的containsKey方法实现)
1 public boolean contains(Object o) { 2 return map.containsKey(o); 3 }
2.由于HashSet的实现类中没有get方法,所以只能通过迭代器依次遍历,而不能随机访问(调用HashMap中keySet的迭代器实现)
1 public Iterator<E> iterator() { 2 return map.keySet().iterator(); 3 }
应用示例:
1 Set<String> hashSet = new HashSet<String>(); 2 hashSet.add("D"); 3 hashSet.add("B"); 4 hashSet.add("C"); 5 hashSet.add("A"); 6 for (Iterator iterator = hashSet.iterator(); iterator.hasNext();) { 7 String string = (String) iterator.next(); 8 System.out.print(string+" "); 9 }//D A B C