8.Set接口

Set 接口也继承 Collection 接口,是无序,不可重复的集合。没有索引,最多包含一个null,不能使用普通for循环遍历。

无序(取决hash)是取出顺序与添加顺序不一致,但是多次遍历后取出顺序是一致的。

  1. public interface Set<E> extends Collection<E> {}

9.HashSet

  • 底层是HashMap
  • 值存放于HashMap的key上,value统一为PRESENT
  1. Set set = new HashSet();
  2. set.add("jack"); // 1. 添加成功
  3. set.add("jack"); // 2. 添加失败
  4. set.add(new Person("jack")); // 3. 添加成功
  5. set.add(new Person("jack")); // 4. 添加成功
  6. set.add(new String("tom")); // 5. 添加成功
  7. set.add(new String("tom")); // 6. 添加失败

构造

public HashSet() {
    map = new HashMap<>();
}
public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
}

add(E e):具体分析在HashMap的put方法

private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object(); //占位
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

10.LinkedHashSet

继承自HashSet,且直接实现了 Set 接口。

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
  • 底层是LinkedHashMap
  • 根据元素hashCode中的值决定元素的存储位置,同时使用双向链表维护元素的次序,使得元素看起来插入是有序的

构造

public LinkedHashSet() {
    super(16, .75f, true);//调用父类 HashSet 的构造器
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor); // 16  0.75
}

add()

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

11.TreeSet

  • TreeSet 可以用于排序,底层是用 TreeMap 实现
  • 当使用无参构造器创建 TreeSet 是按照默认key自然排序
  • 可以使用指定排序规则的构造器使 TreeSet 按照指定规则排序
// 这里使用 Comparator接口类型的实现类 作为参数的构造器,这里定义了排序规则
TreeSet<String> treeSet = new TreeSet<>((s1, s2) -> s1.compareTo(s2));

treeSet.add("a");
treeSet.add("b");
treeSet.add("c");

构造

public TreeSet() {
    this(new TreeMap<E,Object>());
}    
public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

add()

public boolean add(E e) {
    return m.put(e, PRESENT)==null;
}