源码分析-Java Set
发布日期:2021-09-25 11:48:30 浏览次数:3 分类:技术文章

本文共 4655 字,大约阅读时间需要 15 分钟。

一,Set

从Java源码看,java是先实现了Map,然后通过包装一个所有value都为null的Map实现了Set集合

Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入

1.HashSet

- 不能保证元素的排列顺序,顺序可能与添加顺序不同
- HashSet不是同步的,如果多个线程同时访问一个HashSet,假设有两个或者两个以上线程同时修改了HashSet集合,则必须通过代码来保证其同步
- 集合元素值可以是null
- HashSet结合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等

2.LinkedHashSet

与HashSet类似,使用元素的hashCode值来存储元素,不同点是同时使用了链表来维护元素的次序,当遍历元素时,会按照元素的添加顺序来访问集合

3.TreeSet

实现了SortedSet接口,采用的数据结构是红黑树,最大的特点是有序(提供Comparable接口支持自然排序和自定义排序),当把一个对象加入TreeSet时,会调用compareTo方法与容器中的元素进行比较,然后根据红黑树结构找到它的存储位置

二,HashSet

1.继承结构
HashSet继承AbstractSet抽象类,实现了Set、Cloneable、Serializable接口

public class HashSet
extends AbstractSet
implements Set
, Cloneable, java.io.Serializable

2.构造函数

都是创建一个map实例对象,HashSet对象的默认大小与HashMap一样都是16,且大小只能是2的幂次方

private transient HashMap
map; /** * Constructs a new, empty set; the backing
HashMap instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); } public HashSet(Collection
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); }

3.add方法

调用的是map的put方法,有返回值,返回值由map的put方法决定,map调用put(key,value),如果存在key,map即返回此key对应的value,则这里add返回false

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

4.iterator方法

HashSet并没有提供类似于get的方法,只提供获取访问元素的迭代器对象,获取map的key集合的迭代器

public Iterator
iterator() { return map.keySet().iterator(); }

5.size等其他各种方法,也是通过委托给map来实现

public int size() {        return map.size();    }

三,LinkedHashSet

1.继承结构

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

2.构造函数

默认的容量是16,负载因子为0.75

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
c) { super(Math.max(2*c.size(), 11), .75f, true); addAll(c); }

都是super调用父类HashSet的构造函数来实现的:

HashSet(int initialCapacity, float loadFactor, boolean dummy) {        map = new LinkedHashMap<>(initialCapacity, loadFactor);    }

由此可以看出,LinkedHashSet借助于LinkedHashMap来实现

四,TreeSet

1.继承结构
NavigableSet是扩展的SortedSet,具有为了给定搜索目标报告最接近匹配项的导航方法

public class TreeSet
extends AbstractSet
implements NavigableSet
, Cloneable, java.io.Serializable

2.构造方法

底层实现时TreeMap

public TreeSet() {        this(new TreeMap
()); }

3.add方法

调用的是TreeMap的put方法,TreeMap底层是用红黑树实现的,就是这个Entry,然后通过一个compare函数不断比较,小于就放左子树,大于就放右子树,如果重复就不入树,从而保证了数据的唯一性,插入完毕后会调用fixAfterInsertion来调整红黑树保持平衡

public boolean add(E e) {        return m.put(e, PRESENT)==null;    }        public V put(K key, V value) {        Entry
t = root; if (t == null) { compare(key, key); // type (and possibly null) check root = new Entry<>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry
parent; // split comparator and comparable paths Comparator
cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else { if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") Comparable
k = (Comparable
) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } Entry
e = new Entry<>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size++; modCount++; return null; }

参考:

转载地址:https://blog.csdn.net/Autumn03/article/details/81217397 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:队列同步器AbstractQueuedSynchronizer(AQS)
下一篇:java中的原子操作Atomic

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月17日 20时40分29秒