JAVA常用数据结构——Set(HashSet、LinkedHashSet、TreeSet)

HashSet

要了解HashSet之前最好先了解HashMap,因为看下源代码就可以发现所谓的Set借口下的实现,底层都是基于Map来保存数据的。

JAVA常用数据结构——Map(HashMap、LinkedHashMap、TreeMap)

java实现原理

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable{
    static final long serialVersionUID = -5024744406713321676L;

    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();
    
    //......
}

此时可以看到HashSet内部维护了一个HashMap<E,Object> map,在其构造函数中可以看到

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

其内部维护了一个HashMap用来进行数据保存数据

基础操作

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

可以看到其保存数据的内容非常简单,就是向Map中将元素作为key保存进Map中,值为一个固定的值。

删除
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

删除也是一个非常简单的逻辑,只是简单的移除Map中的值。并没有其他操作。

查询
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

其实从插入值得时候就可以看出来,其主要是通过将元素保存到Map中的key中,通过这样保存元素的。所以取出元素的时候只需要获取map的key的集合获得的就是保存的元素的内容。

关于HashSet

对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单。当然实际上你看过后面的几个Set实现后会发现所有的Set都很简单,因为都是基于对应Map的实现来做的。

LinkedHashSet

LinkedHashSet基于LinkedHashMap。之前了解过LinkedHashMap可以知道,和HashMap相比,其内部维护了个LinkedList来维护元素的顺序,所以基于LinkedHashMap的LinkedHashSet同样可以保持元素的插入顺序。

java实现原理

在之前HashSet中可以发现其内部维护的map并没有直接初始化掉,而是在构造函数中初始化了map的对象。其实这么做的原因是为其他Set实现类提供方法可以实现不同的Map类型。

    public LinkedHashSet() {
        super(16, .75f, true);
    }
    
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

LinkedHashSet的构造函数中可以看到,其调用了HashSet的构造函数。而对应的构造函数中,初始化的为LinkedHashMap。

基础操作

LinkedHashSet的代码非常非常简单。除去注释后,其代码甚至不到50行其基础操作就全部重用的HashSet的内容,区别在于,HashSet内部此时初始化的为LinkedHashMap。

package java.util;

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = -2851667679971038690L;

    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);
    }

    @Override
    public Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
    }
}

关于LinkedHashMap如何进行增删查改可以查看之前的文章:
JAVA常用数据结构——Map(HashMap、LinkedHashMap、TreeMap)

TreeSet

TreeSet是JAVA中集合的一种有序集合,它的作用是提供有序的Set集合。

java实现原理

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable {
    /**
     * The backing 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();
    
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }
    
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }
    
}

可以看奥其内部使用了NavigableMap来进行数据保存,而这个NavigableMap可以看到在构造函数中被初始化为TreeMap

    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

基础操作

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

    public boolean remove(Object o) {
        return m.remove(o)==PRESENT;
    }

可以看到其内部在新增和删除依旧和之前Set实现类一样,就是简单的将被添加元素作为key放入到Map中。

    /**
     * @throws NoSuchElementException {@inheritDoc}
     */
    public E first() {
        return m.firstKey();
    }

    /**
     * @throws NoSuchElementException {@inheritDoc}
     */
    public E last() {
        return m.lastKey();
    }

当然可以看到,因为是基于TreeMap的,因为TreeMap提供了一些特有的方法,所以TreeSet中这些新的方法被体现出来了。

关于Set

关于Set的内容,可以发现其基本上是使用了Map的功能实现了自己的逻辑,其中很少或者几乎没有太多自己的业务逻辑。


个人水平有限,上面的内容可能存在没有描述清楚或者错误的地方,假如开发同学发现了,请及时告知,我会第一时间修改相关内容。假如我的这篇内容对你有任何帮助的话,麻烦给我点一个赞。你的点赞就是我前进的动力。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值