HashSet
2016-05-16 10:21
204 查看
HashSet
目录
HashSet目录
概述
成员变量
构造方法
成员方法
Summary
概述
前面的文章讨论了Map中的HashMap,它的特点是以key-value形式来保存数据,把key进行hash()后得到hash值,把value存储在table[hash]处,get和put的效率极高,同时它要求key不能重复。之所以把HashMap放在HashSet之前学习,是因为HashSet就是在HashMap的基础之上构造的。Set,集合,与List的最显著的差别,除了里面的元素无序之外,就是Set中不允许存在重复元素,而Map中不允许存在重复key。所以,Set就是仅仅使用了key的Map,而忽略了Map中的value——Set中的value即是Map中的key。
关于时间复杂度,线程不安全和fast-fail的分析,就不赘述了,前面几篇已经说明了。
学习了HashMap之后,HashSet就简单多了。
成员变量
// HashSet的内部是用HashMap来实现的 private transient HashMap<E,Object> map; // 相当于占位,仅仅用来填充HashMap中的value,HashSet仅仅用到了key private static final Object PRESENT = new Object();
构造方法
// 构造HashSet,实际上得到的是HashMap public HashSet() { map = new HashMap<>(); } /** * 构造HashSet,包含全部的c,0.75f是默认的load factor * c.size()/.75f) + 1是initialcapacity */ public HashSet(Collection<? extends E> 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); } /** * 这个私有构造器只给LinkedHashSet用的 * * @param initialCapacity the initial capacity of the hash map * @param loadFactor the load factor of the hash map * @param dummy ignored (distinguishes this * constructor from other int, float constructor.) * @throws IllegalArgumentException if the initial capacity is less * than zero, or if the load factor is nonpositive */ HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); }
成员方法
/** * 仅仅返回map中key集合的iterator */ public Iterator<E> iterator() { return map.keySet().iterator(); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } /** * 判断map中有无此key */ public boolean contains(Object o) { return map.containsKey(o); } /** * 往Set中插入元素,调用map的操作 */ public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; } public void clear() { map.clear(); } /** * 浅拷贝 */ @SuppressWarnings("unchecked") public Object clone() { try { HashSet<E> newSet = (HashSet<E>) super.clone(); newSet.map = (HashMap<E, Object>) map.clone(); return newSet; } catch (CloneNotSupportedException e) { throw new InternalError(e); } } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden serialization magic s.defaultWriteObject(); // Write out HashMap capacity and load factor s.writeInt(map.capacity()); s.writeFloat(map.loadFactor()); // Write out size s.writeInt(map.size()); // Write out all elements in the proper order. for (E e : map.keySet()) s.writeObject(e); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in any hidden serialization magic s.defaultReadObject(); // Read capacity and verify non-negative. int capacity = s.readInt(); if (capacity < 0) { throw new InvalidObjectException("Illegal capacity: " + capacity); } // Read load factor and verify positive and non NaN. float loadFactor = s.readFloat(); if (loadFactor <= 0 || Float.isNaN(loadFactor)) { throw new InvalidObjectException("Illegal load factor: " + loadFactor); } // Read size and verify non-negative. int size = s.readInt(); if (size < 0) { throw new InvalidObjectException("Illegal size: " + size); } // Set the capacity according to the size and load factor ensuring that // the HashMap is at least 25% full but clamping to maximum capacity. capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f), HashMap.MAXIMUM_CAPACITY); // Create backing HashMap map = (((HashSet<?>)this) instanceof LinkedHashSet ? new LinkedHashMap<E,Object>(capacity, loadFactor) : new HashMap<E,Object>(capacity, loadFactor)); // Read in all elements in the proper order. for (int i=0; i<size; i++) { @SuppressWarnings("unchecked") E e = (E) s.readObject(); map.put(e, PRESENT); } } /** * 基于本Set创建一个Spliterator */ public Spliterator<E> spliterator() { return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0); }
Summary
Set与List最明显的两个区别元素无序
元素无重
学习了HashMap的实现及其原理之后,再来学习HashSet就很简单了——HashSet利用了HashMap的数据结构,忽略了value的部分。
本质上来说,Set和Map并无区别。
至此,学习了ArrayList,LinkedList,HashMap以及HashSet,涉及到的数据结构主要是数组,链表和树;当然java.util家族还有其他的TreeSet,TreeMap等,还有子包concurrent下的很多集合类,就不细看了,了解了红黑的插入删除原理,这些相信都难不倒我们这些执着的CodeDesigners。
下一篇将会总结一下Collection家族结构以及Collections这个工具类中的方法。
相关文章推荐
- IDEA CreateProcess error=2
- jsp+sql server
- python requests sslv3 alert handshake failure
- jQuery 常用代码集锦(必看篇)
- 控制台打包unity C#代码为dll
- nRF51中关于SVCALL的使用
- 利用Multipeer Connectivity框架进行WiFi传输
- Android编码规范
- jquery ajax 中的dataType
- Windows搭建安装React Native环境配置
- git 分支详解
- ShareSDK分享使用步骤
- 【WCF】wcf不支持的返回类型
- select into 和 insert into select 两种表复制语句
- 用实例分析H264 RTP payload(RTSP参数分析)
- 【bzoj1603】【 Usaco2008 Oct】打谷机 (阅读理解) 题解&代码
- linux中断原理
- Android开发请求网络方式详解
- 封装JDBC的一个通用增删改查工具类,将数据集rs转为list
- Number_Get_Next产生流水号