Java Collection 08 - Set

  在Java语言规范中,Set和List同属于Java集合框架中的Collection,是一种可以保证不会出现重复元素的数据结构,类似于数学领域中的集合。提供了对同类型数据进行存储、插入、删除和查找等需求的实现过程。本文演示代码段的执行环境基于JDK版本1.7

概述

  Set是Java集合体系中的成员之一,和List接口一样直接继承于Collection。所以,Set本身只是一个接口定义,其定义了对Set集合进行操作的方法API。Set底层依赖的数据结构决定了其无法存储重复元素(如果允许存储null元素的话最多也只能存储一个null元素),而且也无法保证Set集合的元素先后顺序,即在多次重复遍历同一集合的情况下,每次遍历得到的元素返回顺序无法保证一致。Set的特点如下:

  1. Set的底层实现基于map完成,而且Set暴露出去的方法API大多数都是对map方法的包装。
  2. Set会限制保存在其中的对象类型,有些实现会限制null元素,而其他一些实现会限制特定的数据对象类型。尝试向这种Set集合实现中加入不满足条件的元素会对外抛出异常。尝试查找不满条件的元素时根据实现的不同可能会对外抛出异常,或者直接返回false标识查找失败。

  常见的Set实现包括AbstractSetHashSetLinkedHashSetTreeSet等,而TreeSet还实现了SortedSet接口。其结构如图1所以:

图 - 1

关于上述几个具体实现类之间,分别有其适应的应用场景和特点:

  • HashSet

      直接继承于AbstractSet,实现了Set<E>, Cloneable和Serializable接口;

      底层数据结构依赖于HashMap,可允许存储null元素。具有集合内元素唯一,元素遍历顺序不确定的特点;

      HashSet是一个非线程安全的实现。多线程环境下无法保证线程安全。多线程环境下无法保证线程安全。如果需要在多线程环境下使用LinkedHashSet,则需要采用Collections.synchronizedSet(new HashSet(…));进行包装。

  • LinkedHashSet

      直接继承于HashSet,是HashSet的子类。同时实现了Set<E>, Cloneable和Serializable接口;

      底层数据结构依赖于LinkedHashMap,可允许存储null元素。具有集合内元素唯一,遍历顺序确定的特点;

      LinkedHashSet同样是一个非线程安全的实现。多线程环境下无法保证线程安全。如果需要在多线程环境下使用LinkedHashSet,则需要采用Collections.synchronizedSet(new LinkedHashSet(…));进行包装;

      LinkedHashSet中加入的元素不必实现Comparable或者Comparator接口,集合元素相等比较依赖的是equals()方法;

      LinkedHashSet可以保证的遍历顺序基于元素的插入元素产生,且元素插入时既有元素的顺序不会因为新元素的插入而发生变化。

  • TreeSet

      直接继承于AbstractSet,实现了NavigableSet<E>, Cloneable和Serializable接口;

      底层数据依赖于TreeMap,具有集合内元素唯一,遍历顺序确定的特点;

      TreeSet同样是一个非线程安全的实现。多线程环境下无法保证TreeSet使用的线程安全。如果需要在多线程环境下使用LinkedHashSet,则需要采用Collections.synchronizedSet(new TreeSet(…));进行包装;

      TreeSet中加入的元素需要实现Comparable或者Comparator接口,集合元素相等比较依赖的是compareTo()方法。如果未实现上述接口的方法在加入集合中时,会抛出ClassCastException,提示“TTTT cannot be cast to java.lang.Comparable”;

      TreeSet集合维护的元素是基于Comparable或者Comparator接口的compareTo()方法实现的,进行的对象内容上的比较,按照自然排序(升序或者降序)完成元素排序。该集合的元素顺序会随着元素的加入和删除而产生变化。

部分方法

方法声明 备注
int size(); 返回Set集合中的元素总数
boolean isEmpty(); 判断Set集合是否为空,为空时返回true
boolean contains(Object o); 判断Set集合中是否含有元素o
Iterator<E> iterator(); 返回可以游历Set集合的一个迭代器对象
Object[] toArray(); 将当前Set集合中的元素以数组方式返回
<T> T[] toArray(T[] a); 将当前Set集合中的元素以数组方式存储到参数a中
boolean add(E e); 加入一个元素到Set集合尾部
boolean remove(Object o); 从Set集合中移除一个元素
boolean containsAll(Collection<?> c); 当前Set集合中是否包含集合c的所有元素
boolean addAll(Collection<? extends E> c); 将集合c中的元素都加入到Set集合中
boolean removeAll(Collection<?> c); 从Set集合中移除c中所有元素
boolean retainAll(Collection<?> c); 保留当前Set集合中出现在c中的元素,其他元素都移除
void clear(); 清空Set集合
boolean equals(Object o); 相等性判断
int hashCode(); 生成Set集合的散列值

涉及基础知识点

  1. NIL

参考文献

  1. RUNOOB.COM. Java 集合框架 [E]
  2. J Steven Perry. 第 10 单元:Java 集合 [E]
  3. ORACLE. Collections Framework Overview [E]




------------- End of this article, thanks! -------------


  版权声明:本文由N.C.Lee创作和发表,采用署名(BY)-非商业性使用(NC)-相同方式共享(SA)国际许可协议进行许可,转载请注明作者及出处。
  本文作者为 N.C.Lee
  本文标题为 Java Collection 08 - Set
  本文链接为 https://marcuseddie.github.io/2018/java-Collection-Set.html