java数据结构之HashSet和TreeSet以及LinkedHashSet

java

一、HashSet源码注释

public class HashSet<E>

extends AbstractSet<E>

implements Set<E>, Cloneable, java.io.Serializable

{

static final long serialVersionUID = -5024744406713321676L;

//HashSet底层是HashMap

private transient HashMap<E,Object> map;

// 用来在HashMap中所有的key对应的value值指向这个对象

private static final Object PRESENT = new Object();

/**

* 创建空的HashSet,实际上是创建了一个默认实现的HashMap

*/

public HashSet() {

map = new HashMap<>();

}

/**

* 利用集合创建HashSet

*/

public HashSet(Collection<? extends E> c) {

map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));

addAll(c);

}

/**

* 手动指定容量和加载因子创建HashSet

*/

public HashSet(int initialCapacity, float loadFactor) {

map = new HashMap<>(initialCapacity, loadFactor);

}

/**

* 创建指定容量的HashSet

*/

public HashSet(int initialCapacity) {

map = new HashMap<>(initialCapacity);

}

/**

* 底层是LinkedHashSet

*/

HashSet(int initialCapacity, float loadFactor, boolean dummy) {

map = new LinkedHashMap<>(initialCapacity, loadFactor);

}

/**

* 获取迭代器

*/

public Iterator<E> iterator() {

return map.keySet().iterator();

}

/**

* 获取元素数量

*/

public int size() {

return map.size();

}

/**

* 判断是否为空

*/

public boolean isEmpty() {

return map.isEmpty();

}

/**

* 判断HashSet是否存在该 对象

*/

public boolean contains(Object o) {

return map.containsKey(o);

}

/**

* 新增一个元素,这个元素在HashMap中作为Key,而value则是一个公共的Object

*/

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);

}

}

/**

* 将HashSet写入流中

*/

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);

}

/**

* 从流中读取HashSet的元素

*/

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);

}

}

/**

* 分割迭代器

*/

public Spliterator<E> spliterator() {

return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0);

}

}

View Code

二、HashSet源码分析

  1、通过代码可以看到其底层是一个HashMap,存入HashSet中的对象都会作为HashMap中的key来保存起来,所有的key都对应着同一个value。

  private static final Object PRESENT = new Object();

  2、由于所有的元素都是作为key来保存起来的所以当两个元素一样的时候是不会保存第二个的,这样就很好的解决了元素重复的问题,所以HashSet中的 元素是不重复的。

三、TreeSet源码

  

public class TreeSet<E> extends AbstractSet<E>

implements NavigableSet<E>, Cloneable, java.io.Serializable

{

private transient NavigableMap<E,Object> m;

private static final Object PRESENT = new Object();

/**

* Constructs a set backed by the specified navigable map.

*/

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));

}

/**

* 通过集合创建TreeSet,按照元素的自然排序

*/

public TreeSet(Collection<? extends E> c) {

this();

addAll(c);

}

/**

* 通过SortedSet的实现类来创建TreeSet,指定比较器为SortedSet实现类的比较器

*/

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();

}

/**

* 逆序视图

*/

public NavigableSet<E> descendingSet() {

return new TreeSet<>(m.descendingMap());

}

/**

* 元素个数

*/

public int size() {

return m.size();

}

/**

* 集合是否为空

*/

public boolean isEmpty() {

return m.isEmpty();

}

/**

* TreeSet是否包含元素o

*/

public boolean contains(Object o) {

return m.containsKey(o);

}

/**

* 添加元素

*/

public boolean add(E e) {

return m.put(e, PRESENT)==null;

}

/**

* 删除元素

*/

public boolean remove(Object o) {

return m.remove(o)==PRESENT;

}

/**

* 清空集合

*/

public void clear() {

m.clear();

}

/**

* 批量添加元素

*/

public boolean addAll(Collection<? extends E> c) {

// Use linear-time version if applicable

if (m.size()==0 && c.size() > 0 &&

c instanceof SortedSet &&

m instanceof TreeMap) {

SortedSet<? extends E> set = (SortedSet<? extends E>) c;

TreeMap<E,Object> map = (TreeMap<E, Object>) m;

Comparator<?> cc = set.comparator();

Comparator<? super E> mc = map.comparator();

if (cc==mc || (cc != null && cc.equals(mc))) {

map.addAllForTreeSet(set, PRESENT);

return true;

}

}

return super.addAll(c);

}

/**

* 返回视图

*/

public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,

E toElement, boolean toInclusive) {

return new TreeSet<>(m.subMap(fromElement, fromInclusive,

toElement, toInclusive));

}

/**

* 返回小于toElement的元素视图,inclusive为true可以等于toElement

*/

public NavigableSet<E> headSet(E toElement, boolean inclusive) {

return new TreeSet<>(m.headMap(toElement, inclusive));

}

/**

* 返回大于fromElement的元素视图,inclusive为true可以等于fromElement

*/

public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {

return new TreeSet<>(m.tailMap(fromElement, inclusive));

}

/**

* 返回fromElement,toElement中间的 视图

*/

public SortedSet<E> subSet(E fromElement, E toElement) {

return subSet(fromElement, true, toElement, false);

}

/**

* 返回小于toElement的视图

*/

public SortedSet<E> headSet(E toElement) {

return headSet(toElement, false);

}

/**

* 返回大于fromElement的元素视图

*/

public SortedSet<E> tailSet(E fromElement) {

return tailSet(fromElement, true);

}

//获取比较器

public Comparator<? super E> comparator() {

return m.comparator();

}

//返回第一个元素

public E first() {

return m.firstKey();

}

//返回最后一个元素

public E last() {

return m.lastKey();

}

// NavigableSet API methods

/**

* 返回小于e的最大的元素,没有就返回null

*/

public E lower(E e) {

return m.lowerKey(e);

}

/**

* 返回小于或等于e的最大元素,没有返回null

*/

public E floor(E e) {

return m.floorKey(e);

}

/**

* 返回大于等于e的最小元素

*/

public E ceiling(E e) {

return m.ceilingKey(e);

}

/**

* 返回大于e的最小元素

*/

public E higher(E e) {

return m.higherKey(e);

}

/**

* 返回并删除第一个元素

*/

public E pollFirst() {

Map.Entry<E,?> e = m.pollFirstEntry();

return (e == null) ? null : e.getKey();

}

/**

* 返回并删除最后一个元素

*/

public E pollLast() {

Map.Entry<E,?> e = m.pollLastEntry();

return (e == null) ? null : e.getKey();

}

private static final long serialVersionUID = -2479143000061671589L;

}

View Code

四、TreeSet源码分析

  1、TreeSet底层是基于TreeMap的,将加入的元素作为TreeMap的key,使用一个常量类来作为公共的value。

  2、既然是基于TreeMap,说明也是可以自定义构造器或者利用元素的自然排序。说明这个Set的有序的,且元素不会重复。

五、TreeSet和HashSet的区别

  1、TreeSet和HashSet都不能存储重复元素,集合里面的元素都是唯一的。

  2、HashSet是通过元素的Hash值来确定位置,且是无序的。TreeSet中的元素是有序的,通过比较器或者自然排序来对元素进行排序。

  3、HashSet中可以存储null,TreeSet中默认不可以存储null,但是可以通过自己定义比较器来实现null的存储。

  

六、LinkedHashSet和HashSet的区别与联系

   1、通过下面的代码可以看出LinkedHashSet是HashSet的子类,其底层是通过LinkedHashMap来实现数据的存储和排序的 。

public class LinkedHashSet<E>

extends HashSet<E>

implements Set<E>, Cloneable, java.io.Serializable {

private static final long serialVersionUID = -2851667679971038690L;

//调用父类的构造函数,通过HashSet的构造函数可知,LinkedHashSet底层是通过LinkedHashMap来实现的

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<? extends E> c) {

super(Math.max(2*c.size(), 11), .75f, true);

addAll(c);

}

@Override

public Spliterator<E> spliterator() {

return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);

}

}

以上是 java数据结构之HashSet和TreeSet以及LinkedHashSet 的全部内容, 来源链接: utcz.com/z/393677.html

回到顶部