Set的原理浅析 HashSet, TreeSet(NavigableMap)
2016-05-26 21:32
302 查看
Set一个不可重的集合对象。
HashSet,不保证插入的数据顺序,无序,因为使用的是HashMap散列表的形式,允许一个插入一个null。
源码解析:
TreeSet:
TreeSet使用的是NavigableMap来进行数据的存放,并且还可以进行排序,根据TreeSet这个名字也能想到,树本来就是具有排序的。
部分源码分析:
set在开发中,有时特定场景下,还会有用到的,例如想去重,而又不想自己写校验算法去排重(HashSet)。
或者是想去重的同时,按照自己定义的比较器进行排序则使用TreeSet。
HashSet,不保证插入的数据顺序,无序,因为使用的是HashMap散列表的形式,允许一个插入一个null。
源码解析:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { static final long serialVersionUID = -5024744406713321676L; //比较重要的地方,使用的是HashMap来装的数据 private transient HashMap<E,Object> map; // 构建了一个常量对象,后面会使用到 private static final Object PRESENT = new Object(); //初始化HashMap public HashSet() { map = new HashMap<>(); } public Iterator<E> iterator() { return map.keySet().iterator(); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean contains(Object o) { return map.containsKey(o); } /** *当我们使用add方法时,传入的元素做了HashMap的key, *而前面定义的常量对象,则当做了一个没有意义的value, *而这就是set不可重复的实现点,因为HashMap的key是不可重的。 */ 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(); } 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(); } } }上面就是HashSet的简单解析,是借了HashMap的功能来达到不可重的效果,并达到散列存储的效果。也就是插入元素无序。
TreeSet:
TreeSet使用的是NavigableMap来进行数据的存放,并且还可以进行排序,根据TreeSet这个名字也能想到,树本来就是具有排序的。
部分源码分析:
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable { //使用的是NavigableMap来存储数据,而它是扩展了SortedMap的,也就是继承了SortedMap。 private transient NavigableMap<E,Object> m; //同上面的HashSet一样,也是使用的一个常量对象来填充作为value. private static final Object PRESENT = new Object(); TreeSet(NavigableMap<E,Object> m) { this.m = m; } public TreeSet() { this(new TreeMap<E,Object>()); } //构造方法,可以传入自定义的比较器,进行排序 public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } public TreeSet(SortedSet<E> s) { this(s.comparator()); addAll(s); } public Iterator<E> iterator() { return m.navigableKeySet().iterator(); } public Iterator<E> descendingIterator() { return m.descendingKeySet().iterator(); } //次方法是从NavigableSet继承而来,返回set中元素的逆序排序。 public NavigableSet<E> descendingSet() { return new TreeSet<>(m.descendingMap()); } public int size() { return m.size(); } //同样是将插入的对象作为key,value使用的是常量对象。 public boolean add(E e) { return m.put(e, PRESENT)==null; } //次方法也是从NavigableSet继承而来,返回的是部分集合元素,从fromElement到toElement,两个boolean类型分别表示是否需要包含两端元素。 public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new TreeSet<>(m.subMap(fromElement, fromInclusive, toElement, toInclusive)); } public NavigableSet<E> headSet(E toElement, boolean inclusive) { return new TreeSet<>(m.headMap(toElement, inclusive)); } public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { return new TreeSet<>(m.tailMap(fromElement, inclusive)); } public Comparator<? super E> comparator() { return m.comparator(); } public E lower(E e) { return m.lowerKey(e); } public E floor(E e) { return m.floorKey(e); } public E ceiling(E e) { return m.ceilingKey(e); } public E higher(E e) { return m.higherKey(e); } private static final long serialVersionUID = -2479143000061671589L; }
set在开发中,有时特定场景下,还会有用到的,例如想去重,而又不想自己写校验算法去排重(HashSet)。
或者是想去重的同时,按照自己定义的比较器进行排序则使用TreeSet。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树