Java数据结构-------Set
三种常用Set:HashSet、LinkedHashSet、TreeSet
set类继承关系:
概述
Set是对对应Map的一种封装,Set中的元素不可以重复。
HashSet对应 HashMap、LInkedHashSet对应LinkedHashMap、TreeSet对应TreeMap
HashSet特点
1 不保证set的迭代顺序,特别是它不保证该顺序恒久不变;
2 不允许有重复元素,这是因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个private static final Object PRESENT = new Object();
3 非线程安全的;
4 HashSet通过iterator()返回的迭代器是fail-fast的(参考http://www.cnblogs.com/chenssy/p/3870107.html)。
HashSet源码分析,LInkedHashSet和TreeSet类似
成员变量
两个重要的成员变量:map、PRESENT
1)map:HashSet基于一个HashMap实现;
2)PRESENT:作为HashMap中的value;
1 public class HashSet<E> 2 extends AbstractSet<E> 3 implements Set<E>, Cloneable, java.io.Serializable 4 { 5 static final long serialVersionUID = -5024744406713321676L; 6 7 private transient HashMap<E,Object> map; 8 //定义一个"虚拟"的static final Object对象作为HashMap的value 9 // Dummy value to associate with an Object in the backing Map 10 private static final Object PRESENT = new Object();
构造函数
//构造函数,即新建一个HashMap,默认初识容量为16,加载因子为0.75。 public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } 。。。
查找
HashSet提供了contains(Object o)查看是否包含指定元素的方法,其底层调用的是HashMap.containsKey(Object key)判断是否包含指定key。
1 //Set是否含有元素o,即map中是否含有该key 2 public boolean contains(Object o) { 3 return map.containsKey(o); 4 }
添加
HashSet提供了add(E e)添加元素的方法,其调用的是底层HashMap中的put(K key, V value)方法,首先判断元素(也就是key)是否存在,如果不存在则插入,如果存在则不插入,这样HashSet中就不存在重复值。
1 //如果此set中尚未包含指定元素,则添加指定元素 2 public boolean add(E e) { 3 return map.put(e, PRESENT)==null; 4 }
底层:当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该值确定对象在HashSet中的存储位置。在HashSet中,不能同时存放两个相等的元素,而判断两个元素相等的标准是两个对象通过equals方法比较相等并且两个对象的HashCode方法返回值也相等。
注意:对于HashSet中保存的对象,请注意正确重写其equals和hashCode方法,以保证放入的对象的唯一性。
清空与删除
1 //如果指定元素存在于此set中,则将其移除 2 public boolean remove(Object o) { 3 return map.remove(o)==PRESENT; 4 } 5 6 //从此set中移除所有元素 7 public void clear() { 8 map.clear(); 9 }
其他
1 //返回此set中的元素的数量 2 public int size() { 3 return map.size(); 4 } 5 6 //如果此set不包含任何元素,则返回 true 7 public boolean isEmpty() { 8 return map.isEmpty(); 9 } 10 11 //返回此 HashSet实例的浅表副本 12 @SuppressWarnings("unchecked") 13 public Object clone() { 14 try { 15 HashSet<E> newSet = (HashSet<E>) super.clone(); 16 newSet.map = (HashMap<E, Object>) map.clone(); 17 return newSet; 18 } catch (CloneNotSupportedException e) { 19 throw new InternalError(e); 20 } 21 }
迭代器
1 //返回对此 set中元素进行迭代的迭代器 2 public Iterator<E> iterator() { 3 return map.keySet().iterator(); //HashMap.keySet()返回<key, value>对中的key集 4 }
参考资料
https://www.cnblogs.com/CherishFX/p/4790735.html