Set 集合类

相比于前面两篇文章写的关于ArrayList和LinkedList,Set集合与他们的不同之处在于,Set不允许数据重复。

Set类集合类库的简化图如下。
Set类集合类库简化图-摘自java编程思想

可见:Set实现了Collection和Iterator

几种常见的Set:

  • Set(interface): 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals() 方法以确保对象的唯一性。Set和Collection有完全一样的接口。Set接口不保证维护元素的次序。
  • HashSet: 为快速查找而设计的Set,存入HashSet的元素必须定义hashCode()
  • TreeSet:保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。元素必须实现Comparable接口
  • LinkedHashSet: 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的顺序)。于是在使用迭代器遍历Set时,结果会按照元素插入的次序显示。元素也必须定义hashCode()方法

HashSet原码阅读总结

private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();

HashSet的底层数据存储靠的是HashMap,且只是用了HashMap的key,value统一使用一个Object对象来填充。

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

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

HashSet一共提供了4个构造器,都是初始化了一个HashMap对象。

public Iterator<E> iterator() {
    return map.keySet().iterator();
}

HashSet在遍历的时候,取回了HashMap的key,对Key进行遍历。而HashMap的value则都被用object填充了。

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

添加一个元素的时候,就是往map里面添加了一条记录,key添加的元素,value为统一的object对象

public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
}

移除一个元素的时候,调用的是map的remove操作。

关于HashMap的操作原理,会在以后的博客中写上,因为我还没看到HashMap。哈哈哈哈哈哈

TreeSet原码阅读总结

private transient NavigableMap<E,Object> m;

TreeSet 底层基于NavigableMap 实现,跟HashMap一样,只使用了NavigableMap的key,value统一设置为null

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(Collection<? extends E> c) {
    this();
    addAll(c);
}
public TreeSet(SortedSet<E> s) {
    this(s.comparator());
    addAll(s);
}

TreeSet 提供了五个构造器,全用于初始化NavigableMap 实例

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

添加一个元素,使用的是 map的put方法

public boolean remove(Object o) {
    return m.remove(o)==PRESENT;
}

删除一个元素,使用的是map 的remove 方法

其实Set的底层使用的都是Map,一些具体的细节,可以在今后的Map原码阅读中去研究。

LinkedHashSet原码阅读
LinkedHashSet 基于LinkedHashMap实现。它继承了HashSet,实现了Set

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

LinkedHashSet 提供了四个构造器。这四个构造器都调用了HashSet的构造器,第三个参数为无效参数。
从第三个构造器可知,LinkedHashSet的默认长度为16,扩容因子默认为0.75。

本文中提及的TreeSet和LinkedHashSet如何确保有序和保持插入顺序,将会在写Map的文章中再描述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值