Set 集合
和List一样,继承Collection接口,不同的是Set中不能包含重复的元素,无序,并且最多只能允许一个null值。Set常见的实现类有:HashSet、TreeSet和LinkedHashSet。
1.HashSet
HashSet是一个没有重复元素的集合。它是由HashMap实现的,不能保证元素的顺序,重要的是HashSet允许使用null元素。
HashSet是非同步的。如果多个线程同时访问一个hashset,而其中至少一个线程修改了该hashset,那么它必须保持外部同步。
Set s = Collections.synchronizedSet(new HashSet(...));
构造方法:
1)无参构造方法
通过hashset的构造函数可以看出创建hashset实际上就是创建一个hashmap。但是无参构造方法创建的hashset将会是一个容量为16,装载因子为0.75的hashmap。
public HashSet() { map = new HashMap<>(); }
2)有参构造方法
通过有参的构造方法可以指定内部hashmap的容量和装载因子
public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); }public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); }
3)构造方法的参数是一个集合
如果参数是一个集合,那么hashset会把传入集合的大小除以0.75再加上1与16进行比较,取较大的那个值作为hashmap的容量。
public HashSet(Collection c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }
具体的源码分析
hashset对存入的元素有一些要求,为了保证存入元素的唯一性,存储在hashset中的元素必须重写hashcode()和equals()方法,重写hashcode方法是为了根据元素自身的特性确定元素的hash值,进而确定元素在hashset中的位置,而重写equals方法是为了解决哈希冲突,当两个元素通过hashcode计算出的hash值相同的时候就发生了hash冲突,这个时候,根据元素的equals方法来判断两个元素是否相同,如果两个元素的内容相同,那么重复的元素便不会存储;如果内容不同,就会通过一个单向链表来存储发送hash冲突的元素,在Java8中,若谷冲突的次数超过来8次,就会将单向链表转化为红黑树,从而将最坏的情况下的性能从O(n)提高到O(logn)。
2.TreeSet
是一个有序的集合,是一个set集合。继承abstractset,实现了navigableset,cloneable,serializable接口。
源码分析
3.LinkedHashSet
总结面试问题: