JDK “偷懒“ 操作 之 Set 集合

大家好,相信大家在平时的日常工作、学习中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里面实现最最最简单的,代码简单,通俗易懂,妈妈再也不担心我看源码了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值