Java编程拾遗『LinkedHashSet』

根据之前讲HashSet和HashMap的关系,TreeSet和TreeMap的关系,我们也能猜测出来LinkedHashSet肯定也是通过LinkedHashMap实现的,只是LinkedHashMap所有键值对的value都是一个特定的值,所有的key便组成了LinkedHashSet的所有集合元素,并能保证所有的集合元素按插入有序。LinkedHashSet类的继承关系如下图所示:

可以看到,LinkedHashSet实现了Set接口,继承了HashSet类。HashSet是基于HashMap实现的,HashSet中的方法操作的其实是内部的HashMap实例。如果可以让HashSet中的方法操作LinkedHashMap实例,那么就能轻松的实现LinkedHashSet了。其实Java API中也是这样实现的,下面会详细讲述。

1. 使用示例

public static void main(String[] args) {
    Set<Integer> linkedHashSet = new LinkedHashSet<>();
    linkedHashSet.add(1);
    linkedHashSet.add(5);
    linkedHashSet.add(3);

    for (Integer item : linkedHashSet) {
        System.out.println(item);
    }
}

运行结果:

1
5
3

LinkedHashSet中的元素按插入有序。

2. 方法说明

LinkedHashSet继承了HashSet,实现了Set接口,除构造函数之外的方法,都实现自Set接口。

2.1 构造方法

S.N.方法说明
1public LinkedHashSet()默认构造函数,构造容量为16,负载因子为0.75的空LinkedHashSet
2public LinkedHashSet(int initialCapacity)构造容量为initialCapacity,负载因子为0.75的空LinkedHashSet
3public LinkedHashSet(int initialCapacity, float loadFactor)构造容量为initialCapacity,负载因子为loadFactor的空LinkedHashSet
4public LinkedHashSet(Collection<? extends E> c)通过Collection对象构造LinkedHashSet

2.2 Set接口

S.N.方法说明
1boolean add(E e)向Set中添加一个元素
2boolean addAll(Collection<? extends E> c)将Collection中的元素添加到Set中
3boolean contains(Object o)判断Set中是否包含o元素
4boolean containsAll(Collection<?> c)判断Collection中的元素是否全部存在于Set中
5boolean equals(Object o)equals方法
6int hashCode()hashCode方法
7boolean isEmpty()判断Set是否为空
8Iterator<E> iterator()返回Set的单向Iterator迭代器
9boolean remove(Object o)删除Set中的元素o
10boolean removeAll(Collection<?> c)删除Set中包含的Collection的所有元素,如果c也为Set,表示求差集
11boolean retainAll(Collection<?> c)保留Set中包含的Collection的所有元素,如果c也为Set,表示求交集
12int size()返回Set元素个数
13default Spliterator<E> spliterator()返回Set的并行流Spliterator迭代器
14Object[] toArray()Set转Object[]数组
15<T> T[] toArray(T[] a)Set转特定类型数组

3. 实现源码分析

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

以上就是LinkedHashSet类的全部实现,看着不免有些懵逼。为什么只有构造函数,说好的通过LinkedHashMap实现的呢,连LinkedHashMap的影子都没看到。其实奥秘就在那个super(来自HashSet的构造函数)中,我们来看一下HashSet中这个构造函数的实现:

/**
 * 构建一个空的按插入有序的LinkedHashMap,LinkedHashMap容量为initialCapacity,负载因子为loadFactor
 *
 * @param      initialCapacity   LinkedHashMap容量
 * @param      loadFactor        LinkedHashMap负载因子
 * @param      dummy             忽略,仅用于与其他构造函数区分
 */
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    //调用的是LinkedHashMap构造函数,返回LinkedHashMap实例,map的运行时类型为LinkedHashMap
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

所以,之后所有HashSet中所有方法对于map的操作,操作的都是LinkedHashMap实例,所以可以保证LinkedHashSet中元素按插入有序。

4. LinkedHashSet特点

LinkedHashSet实现了Set接口,内部是通过LinkedHashMap实现的,这也决定了HashSet有如下特点:

  • LinkedHashSet中可以保证没有重复元素
  • 添加、删除、判断元素是否存在,效率很高,时间复杂度为O(1)。
  • LinkedHashSet可以保证元素按插入有序

参考链接:

  1. Java API源码
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值