集合类源码(八)Collection之Set(HashSet, LinkedHashSet, TreeSet)

HashSet

先看一下成员变量

// 由此可见内部存储是一个HashMap
private transient HashMap<E,Object> map;

private static final Object PRESENT = new Object();

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

add方法

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

仅仅是把新元素作为key,一个事先初始化好的空Object对象作为value,存入HashMap。

同理,contains方法和remove方法都是调用HashMap的方法

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

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

HashSet实现很简单,完全基于HashMap。

LinkedHashSet

先来看继承关系,继承了HashSet

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

本身也没有提供相关CRUD方法

来看下构造方法

public LinkedHashSet() {
    // 调用的父类的方法
    super(16, .75f, true);
}

// 父类(HashSet)构造方法
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    // 和HashSet区别在于new了一个LinkedHashMap
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

这个构造方法是一个包私有的,仅仅提供给LinkedHashSet使用。

LinkedHashSet的实现基于LinkedHashMap

TreeSet

到这里,不用看也能知道,TreeSet的实现基于TreeMap....

来看成员变量

private transient NavigableMap<E,Object> m;

// 人家官方管这个Map中value的默认值叫做“哑值”
private static final Object PRESENT = new Object();

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

TreeSet(NavigableMap<E,Object> m) {
    this.m = m;
}

而add、contains、remove等方法也不必解释了

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

public boolean contains(Object o) {
    return m.containsKey(o);
}

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

ConcurrentSkipListSet

虽然这个名字很长,人家也是线程安全的Set,但是,依然依托于Map的具体实现类

// 内部存储结构
private final ConcurrentNavigableMap<E,Object> m;

// 构造方法
public ConcurrentSkipListSet() {
    m = new ConcurrentSkipListMap<E,Object>();
}

// add
public boolean add(E e) {
    return m.putIfAbsent(e, Boolean.TRUE) == null;
}

// contains
public boolean contains(Object o) {
    return m.containsKey(o);
}

// remove
public boolean remove(Object o) {
    return m.remove(o, Boolean.TRUE);
}

与前面不同的是,ConcurrentSkipListSet内部Map的value值永远是一个  Boolean.TRUE

优点:

1. 基于跳表实现,查找效率高

2. 线程安全

CopyOnWriteArraySet

这里呢,就不是基于Map的了,毕竟没有 CopyOnWriteArrayMap 这个集合类。虽然没有相关Map实现,但是是不是有一个 CopyOnWriteArrayList

private final CopyOnWriteArrayList<E> al;

/**
 * Creates an empty set.
 */
public CopyOnWriteArraySet() {
    al = new CopyOnWriteArrayList<E>();
}

那是怎样去重的呢?

public boolean add(E e) {
    // addIfAbsent:如果没有则添加,就是这样来保证无重复元素的
    return al.addIfAbsent(e);
}

其它都是直接调用其内部数据结构的方法

public boolean contains(Object o) {
    return al.contains(o);
}

public boolean remove(Object o) {
    return al.remove(o);
}

总结:

Set旗下的集合一般都是站在Map集合的肩膀上的,懂了Map,就懂了Set

关于有序和无序:

0. 无序:HashSet

1. 按照自然顺序排序的:TreeSet、ConcurrentSkipListSet

2. 按照添加顺序排序的:LinkedHashSet、CopyOnWriteArraySet

测试程序

public static void main(String[] args) throws Exception {
     deal(new HashSet<>());
     deal(new LinkedHashSet<>());
     deal(new TreeSet<>());
     deal(new ConcurrentSkipListSet<>());
     deal(new CopyOnWriteArraySet<>());
}
private static void deal(Set<String> set){
    set.add("s1");
    set.add("s9");
    set.add("s3");
    set.add("s5");
    set.add("s7");
    set.add("s2");
    set.add("s8");
    System.out.println(set.getClass().getName() + ":" + set);
}

结果:

java.util.HashSet:[s3, s5, s7, s8, s9, s1, s2]
java.util.LinkedHashSet:[s1, s9, s3, s5, s7, s2, s8]
java.util.TreeSet:[s1, s2, s3, s5, s7, s8, s9]
java.util.concurrent.ConcurrentSkipListSet:[s1, s2, s3, s5, s7, s8, s9]
java.util.concurrent.CopyOnWriteArraySet:[s1, s9, s3, s5, s7, s2, s8]

原文地址:https://www.cnblogs.com/LUA123/p/11928908.html

时间: 2024-10-16 15:02:04

集合类源码(八)Collection之Set(HashSet, LinkedHashSet, TreeSet)的相关文章

java集合类源码剖析

java集合类源码剖析 hashmap 底层实现 HashMap.Entry数组,数组+拉链 static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; } Entry对象代表了HashMap中的一个元素(键值对) hashCode相同(碰撞)的元素将分配到Entry数组的同一个桶中 同一个桶中的Entry对象由nex

hashSet linkedHashSet treeSet 一点区别

上代码先: Set<String> hashSet=new HashSet<String>(); hashSet.add("thireBottom"); hashSet.add("thirdTop"); System.out.println(hashSet); Set<String> linkedSet=new LinkedHashSet<String>(); linkedSet.add("thireBott

java 集合类源码分析--arrayList

ArrayList就是传说中的动态数组,就是Array的复杂版本,它提供了如下一些好处:动态的增加和减少元素.灵活的设置数组的大小...... 认真阅读本文,我相信一定会对你有帮助.比如为什么ArrayList里面提供了一个受保护的removeRange方法?提供了其他没有被调用过的私有方法? 首先看到对ArrayList的定义: public class ArrayList<E> extends AbstractList<E> implements List<E>,

java 集合类源码分析--linkedlist

一.源码解析 1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clone()与toArray()9.遍历数据:Iterator()二.ListItr 一.源码解析 1. LinkedList类定义. public class LinkedList<E> extends AbstractSequentialList<E> implements List

Java集合类源码解析:AbstractList

今天学习Java集合类中的一个抽象类,AbstractList. 初识AbstractList AbstractList 是一个抽象类,实现了List<E>接口,是隶属于Java集合框架中的 根接口 Collection 的分支,由其衍生的很多子类因为拥有强大的容器性能而被广泛应用,例如我们最为熟悉的ArrayList,这是它的类继承结构图: 特殊方法 AbstractList 虽然是抽象类,但其内部只有一个抽象方法 get(): abstract public E get(int index

Java集合类源码解析:AbstractMap

目录 引言 源码解析 抽象函数entrySet() 两个集合视图 操作方法 两个子类 参考: 引言 今天学习一个Java集合的一个抽象类 AbstractMap ,AbstractMap 是Map接口的 实现类之一,也是HashMap.TreeMap.ConcurrentHashMap 等的父类,它提供了Map 接口中方法的基本实现(关于Map接口有疑惑的同学可参考 Java集合类根接口:Collection 和 Map) 源码解析 因为 AbstractMap 类是实现Map接口的抽象类,所以

Java集合类源码解析:Vector

引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector. 为什么说是它兄弟呢?因为从容器的构造来说,Vector 简直就是 ArrayList 的翻版,也是基于数组的数据结构,不同的是,Vector的每个方法都加了 synchronized 修饰符,是线程安全的. 类声明 用idea打开 Vector 的源码,不难发现,它的类声明跟 ArrayList 一模一样,都是继承了AbstractList,并且都实现了RandomAccess 接口,遍历元素用for循

java集合类源码分析-concurrentHashMap

Java Core系列之ConcurrentHashMap实现(JDK 1.7) ConcurrentHashMap类似Hashtable,是HashMap更高效的线程安全版本的实现.不同于Hashtable简单的将所有方法标记为synchronized,它将内部数组分成多个Segment,每个Segment类似一个Hashtable,从而减少锁的粒度,并且它内部有一些比较tricky实现,让get操作很多时候甚至不需要锁(本文代码基于JDK 1.7,它在JDK 1.6的基础上做了进一步的优化,

Java集合类源码同步否~

存档~~~~ Synchronized,volatile,lock 锁->[就绪队列,堵塞队列] 第一个是jvm层次实现的.与volatile不同的是,后者不能从工作内存写回到主存.所以后者常用于类变量的同步 lock来说,在竞争资源激烈的情况下,效率最高. 引用下:http://zzhonghe.iteye.com/blog/826162 synchronized: 在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的.原因在于,编译程序通常会尽可能的进行优化

java 集合类源码分析--Vector

首先我们来看JDK源码中Java.util.Vector的代码,剔除所有的方法和静态变量, Java.lang.Vector的核心代码如下: public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { protected Object[] elementData; /** * The number of