重学Java集合类(四)—— Set接口

前言

Set不保存重复的元素。Set中最常被使用的是测试归属性,你可以很容易的询问某个对象是否在某个Set中。Set具有与Collection完全一样的接口,因此没有任何额外的功能。实际上Set就是Collection,只是行为不同。

Set接口

Set接口内容如下图:
这里写图片描述
从上图中我们可以很清晰的看出,Set接口继承了Collection接口,甚至可以说Set接口就是Collection接口。

常用实现类

Set
|------HashSet
|             |-------LinkedHashSet
|------TreeSet

HashSet

HashSet是基于HashMap来实现的,操作很简单,更像是对HashMap做了一次“封装”,而且只使用了HashMap的key来实现各种特性。

内部成员

    // HashSet内部包含了一个HashMap
    private transient HashMap<E,Object> map;

    // 定义一个虚拟的Object。
    // PRESENT是向map中插入key-value对应的value
    // 向map中添加键值对时,键值对的值固定是PRESENT
    private static final Object PRESENT = new Object();

初始化

HashSet提供如下四种初始化方法:

    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的初始化过程可以看作是内部HashMap的初始化过程,不再赘述。

关键方法

正如前言中所述,Set不保存重复的元素,Set中最常被使用的是测试归属性。Set中最频繁被调用的方法就是add、remove、contains三个方法。

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

add方法的实现逻辑就是往内部成员map中添加e和PRESENT组成的键值对,根据返回值是否为null判断是否添加成功。HashMap中如果内部已经存在key为e的键值对,则返回对应的value,否则返回null。此处可以看到,HashSet内部的map中所有键值对的value都是PRESENT。

remove方法
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

remove方法调用HashMap的remove方法,根据返回值判断是否删除成功。

contains方法
    public boolean contains(Object o) {
        return map.containsKey(o);
    }

contains方法通过调用HashMap的containsKey方法判断是否包含相关对象。

LinkedHashSet

LinkedHashSet继承自HashSet,源码更少、更简单,唯一的区别是LinkedHashSet内部使用的是LinkHashMap。这样做的意义或者好处就是LinkedHashSet中的元素顺序是可以保证的,也就是说遍历序和插入序是一致的。

    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }

    public LinkedHashSet() {
        super(16, .75f, true);
    }

    public LinkedHashSet(Collection<? extends E> c) {
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }

LinkedHashSet通过调用HashSet包私有的构造方法来初始化,使用LinkedHashMap代替HashMap作为对象的存储载体。

总结

本文主要讲述了Set接口及其部分实现类的内部逻辑,Set接口的更多高级实现,例如TreeSet后续还会有讲述,希望能对读者有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值