大家好,相信大家在平时的日常工作、学习中Set集合用的是比较多的吧
今天,我们就看看JDK中Set的迷幻操作
先看一下HashSet
内部维护了一个HashMap,就这?
private transient HashMap<E,Object> map;
每一个构造函数都是在初始化这个map
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);
}
构造函数里面还有一个彩蛋,等会再说
其实你已经猜到了HashSet其他方法是怎么实现的,看看其最常用的方法吧
size():
public int size() {
return map.size();
}
isEmpty():
public boolean isEmpty() {
return map.isEmpty();
}
contains():
public boolean contains(Object o) {
return map.containsKey(o);
}
上面这些方法都太敷衍了,我们看看其实现逻辑最复杂的方法
add()方法,添加一个元素就是像map里面put一个元素,利用HashMap key不重复的特点保证Set里的值不重复
假如set添加成功了,也就是map里面没有对应的key,put()返回null,add()就会返回true
添加不成功,即已经包含这个值了,put()就会返回old value,也就不为null
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
value是一个默认值,所有entry的value都是这个
private static final Object PRESENT = new Object();
remove()与add()同理,不多bb
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
再看一下LinkedHashSet
只给你们看一行代码你们就懂了
public class LinkedHashSet<E> extends HashSet<E>
还有我们刚刚说的HashSet构造函数的一个小彩蛋
dummy:(尤指缝制或陈列服装用的)人体模型;仿制品;仿造物;笨蛋;蠢货 假的
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
是的,使用有dummy这个参数的构造方法的人只有LinkedHashSet一个。
LinkedHashMap大家都知道,继承于HashMap,之前我再说HashMap时说过,HashMap内部有几个默认空实现的方法,就是为儿子LinkedHashMap准备的,方便其在增加、删除、访问元素后进行操作,LinkedHashMap内部维护了一个双向链表,用于实现指定顺序,可以用其实现LRU算法
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
LinkedHashSet内部实现逻辑最复杂的方法就是一个具有两行代码的构造方法,我吐了,这操作,实在是太懒了
最后给大家看看一个Set,TreeSet,其实我已经不用说了,只要知道有TreeMap的兄弟就猜到了
其实略有差别
TreeSet内部维护了一个NavigableMap
private transient NavigableMap<E,Object> m;
你可以自由的传入一个实现了NavigableMap的Map,当然,这是他儿子才能享受的待遇
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
你来的话,他还是给你TreeMap
public TreeSet() {
this(new TreeMap<E,Object>());
}
不仅仅是这些大家经常接触的Set,还有一个看似非常高大上的Set
CopyOnWriteArraySet
内部维护了一个CopyOnWriteArrayList,好家伙,终于不是Map,我哭了
private final CopyOnWriteArrayList<E> al;
你能想到的一切操作都是由CopyOnWriteArrayList他完成的,怎么样,是不是瞬间就觉得CopyOnWriteArraySet不高大上了,辣鸡一个
怎么样,看完这个Set的一些实现,是不是觉得这是JDK里面实现最最最简单的,代码简单,通俗易懂,妈妈再也不担心我看源码了