Java集合-Set
# Java集合-Set

set继承了collection的接口,而set集合是不允许有重复元素的
SortedSet 继承了 Set 的接口。SortedSet 中的内容是排序的唯一值,排序的方法是通过比较器(Comparator)。
NavigableSet 继承了 SortedSet 的接口。它提供了丰富的查找方法:如"获取大于/等于某值的元素"、“获取小于/等于某值的元素”等等。
HashSet 类依赖于 HashMap,它实际上是通过 HashMap 实现的。HashSet 中的元素是无序的、散列的。
TreeSet 类依赖于 TreeMap,它实际上是通过 TreeMap 实现的。TreeSet 中的元素是有序的,它是按自然排序或者用户指定比较器排序的 Set。
LinkedHashSet 是按插入顺序排序的 Set。
EnumSet 是只能存放 Emum 枚举类型的 Set。
# HashSet类
HashSet是通过HashMap来实现的,因此HashSet中的元素是无序的、散列的。具有以下特点:
HashSet通过继承AbstractSet实现了Set接口中的骨干方法。HashSet实现了Cloneable,所以支持克隆。HashSet实现了Serializable,所以支持序列化。HashSet中存储的元素是无序的。HashSet允许 null 值的元素。HashSet不是线程安全的。
其中HashSet的核心是通过基于HashMap来实现的:
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
通过这个map去实现诸如add、remove、clear方法。
// 返回迭代器
public Iterator<E> iterator() {
return map.keySet().iterator();
}
// 大小
public int size() {
return map.size();
}
// 判断非空
public boolean isEmpty() {
return map.isEmpty();
}
// 是否包含某个元素
public boolean contains(Object o) {
return map.containsKey(o);
}
// 如果不存在添加的元素,则添加元素
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
// 如果存在,则从此集合中删除对象
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
// 清除
public void clear() {
map.clear();
}
# TreeSet类
TreeSet类依赖于 TreeMap,它实际上是通过 TreeMap 实现的。TreeSet中的元素是有序的,它是按自然排序或者用户指定比较器排序的 Set。具有以下特点:
TreeSet通过继承AbstractSet实现了NavigableSet接口中的骨干方法。TreeSet实现了Cloneable,所以支持克隆。TreeSet实现了Serializable,所以支持序列化。TreeSet中存储的元素是有序的。排序规则是自然顺序或比较器(Comparator)中提供的顺序规则。TreeSet不是线程安全的。
和HashSet类似,内部的核心是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();
通过这个map去实现其他核心方法:
public int size() {
return m.size();
}
public boolean isEmpty() {
return m.isEmpty();
}
public boolean contains(Object o) {
return m.containsKey(o);
}
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
public void clear() {
m.clear();
}
# LinkedHashSet类
LinkedHashSet 是按插入顺序排序的 Set。具有以下特点:
LinkedHashSet通过继承HashSet实现了Set接口中的骨干方法。LinkedHashSet实现了Cloneable,所以支持克隆。LinkedHashSet实现了Serializable,所以支持序列化。LinkedHashSet中存储的元素是按照插入顺序保存的。LinkedHashSet不是线程安全的。
构造方法
LinkedHashSet 有三个构造方法,无一例外,都是调用父类 HashSet 的构造方法。
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
而这三个构造方法所调用的父类构造方法如下:
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
相当于是创建了一个LinkedHashMap,由于LinkedHashMap实际上为一个双链表,所以LinkedHashSet 就是维护了一个双链表。由双链表的特性可以知道,它是按照元素的插入顺序保存的。所以,这就是 LinkedHashSet 中存储的元素是按照插入顺序保存的原理。
# EnumSet类
EnumSet类定义如下:
public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
implements Cloneable, java.io.Serializable {}
具有以下特点:
EnumSet继承了AbstractSet,所以有Set接口中的骨干方法。EnumSet实现了Cloneable,所以支持克隆。EnumSet实现了Serializable,所以支持序列化。EnumSet通过<E extends Enum<E>>限定了存储元素必须是枚举值。EnumSet没有构造方法,只能通过类中的static方法来创建EnumSet对象。EnumSet是有序的。以枚举值在EnumSet类中的定义顺序来决定集合元素的顺序。EnumSet不是线程安全的。