源码分析-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 HashSetextends AbstractSet implements Set , Cloneable, java.io.Serializable
2.构造函数
都是创建一个map实例对象,HashSet对象的默认大小与HashMap一样都是16,且大小只能是2的幂次方private transient HashMapmap; /** * 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返回falsepublic boolean add(E e) { return map.put(e, PRESENT)==null; }
4.iterator方法
HashSet并没有提供类似于get的方法,只提供获取访问元素的迭代器对象,获取map的key集合的迭代器public Iteratoriterator() { return map.keySet().iterator(); }
5.size等其他各种方法,也是通过委托给map来实现
public int size() { return map.size(); }
三,LinkedHashSet
1.继承结构public class LinkedHashSetextends HashSet implements Set , Cloneable, java.io.Serializable {
2.构造函数
默认的容量是16,负载因子为0.75public 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 TreeSetextends AbstractSet implements NavigableSet , Cloneable, java.io.Serializable
2.构造方法
底层实现时TreeMappublic 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) { Entryt = 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2024年04月17日 20时40分29秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
服务器端开发经验总结 Linux C语言
2021-06-30
将网站程序放在tmpfs下
2021-06-30
使用Nginx的proxy_cache缓存功能取代Squid
2021-06-30
nginx 反向代理,动静态请求分离,proxy_cache缓存及缓存清除
2021-06-30
nginx 的proxy_cache才是王道
2021-06-30
Nginx proxy_cache 使用示例
2021-06-30
Nginx源代码分析 - 日志处理
2021-06-30
使Apache实现gzip压缩
2021-06-30
Memcached在大型网站中应用
2021-06-30
Hadoop简要介绍
2021-06-30
squid中的X-Cache和X-Cache-Lookup的意义
2021-06-30
squid 优化指南
2021-06-30
编程方式刷新Squid缓存服务器的五种方法
2021-06-30
centos vnc配置笔记
2021-06-30
Linux服务器网络开发模型
2021-06-30
nginx虚拟目录设置 alias 和 root
2021-06-30
理解http响应头中的Date和Age
2021-06-30
四层和七层负载均衡的区别
2021-06-30
设置Squid Cache_mem大小
2021-06-30
squid日志文件太大,怎样处理?
2021-06-30