5.蹭饭之王-Set

510 阅读1分钟

Set作为和List同层级的集合,却没有与之比肩的热度.我在平时也少用,并觉得有些许陌生.或许是他"蹭饭"的缘故吧

1.Set

public interface Set<E> extends Collection<E> {

上面便是Set接口的定义信息了,只是简单的继承了Collection,再结合Doc注释,得出以下信息:

  1. Set不包含重复元素,最多包含一个null元素(但这只是协议,还得看具体实现).
  2. 是通过equals()方法实现重复判断的.

前排提示: 建议先阅读Map小节内容,因为在一些Set实现里面用了很多和Map的相关的内容,这么做的原因也是为了减少代码量,只需要测试一次,便可满足多处使用,但这样会接口之间的关系会很混乱.

2. HashSet

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{

1. 概述

上述一些类说明就不说了,前面也提过.HashSet由哈希表构成的Set实现,不保证元素的迭代顺序,允许null元素.等下我们就能看到,HashSet其实很简单,因为他内部使用的就是HashMap.

2.方法

private transient HashMap<E,Object> map;
// 默认的value值
private static final Object PRESENT = new Object();

public HashSet() {
	map = new HashMap<>();
}

HashSet再初始化时也初始化了内部的HashMap对象,同时HashSet自身的方法不多.看几个主要的.

add()

public boolean add(E e) {
	return map.put(e, PRESENT)==null;
}

短短一行代码便完成了新增的操作,利用HashMapkey本身不能重复的特性,实现了HashSet.对应的key值就是我们要存储的值,而value就是上述新创建的Object对象.

3.杂谈

HashSet其他方法亦是如此,都是使用的HashMap的方法,所以HashSet到这里就结束了.

3. LinkedHashSet

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

1.杂谈

这个类也特别特别简单,就几个方法,还都是用的HashSet的,但是他是一个迭代有序的Set实现,至于迭代有序,其实就是使用的LinkedHashMap.

public LinkedHashSet(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor, true);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

看了上图,应该都懂了吧,所以,LinkedHashSet也结束了.

其实TreeSet大家应该也能猜到了,他使用的是TreeMap,这点从构造函数也能看出.