同样是存储一组同类型元素都继承Collection接口,但Set集合确与List有着很多不同,Set集合不能包含重复值空值,List集合可以;Set集合没有get之类单个元素输出的方法,只能通过返回迭代器遍历进行取值,但List集合可以。主要是应为Set类内部是通过Map类实现来进行操作。
1.HashSet
源码如下
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
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 boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public Iterator<E> iterator() {
return map.keySet().iterator();
}
public boolean contains(Object o) {
return map.containsKey(o);
}
//....
}
HashSet内部方法的实现其实就是在对一个内部HashMap对象做操作,所以是一个无序,非线程安全的集合。存储元素的值作为HashMap的Key,存储到Map中。key值不能是null值,所以Set的元素就不能含有null值。通过返回key迭代器取值
2.TreeSet
源码如下
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* Constructs a set backed by the specified navigable map.
*/
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
public TreeSet() {
this(new TreeMap<E,Object>());
}
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
//....
}
与HashSet不同,TreeSet继承NavigableSet,实现返回头部元素,尾部元素等导航集合的方法,同样内部还是通过操作一个TreeMap对一系列方法进行实现,所以TreeSet相对于HashSet是有序的,同样继承了Map的一些特性,比如元素不能有重复值,不能为null。