博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
「译」Java集合框架系列教程四:Set接口
阅读量:4109 次
发布时间:2019-05-25

本文共 4504 字,大约阅读时间需要 15 分钟。

原文:

译文:

一个Set是一个不能包含重复元素的集合。它映射了数学意义上的集合抽象。Set接口只是在继承自Collecton接口的方法基础之上加上不允许元素重复的限制。Set也对equals和hashCode的行为规约施加了更强的限制,使得Set实例允许进行有意义的比较,即使他们的具体实现不同。两个集合实例相等(equal)如果它们包含相同的元素。

一个Set是一个不能包含重复元素的集合。它映射了数学意义上的集合抽象。Set接口只是在继承自Collecton接口的方法基础之上加上不允许元素重复的限制。Set也对equals和hashCode的行为规约施加了更强的限制,使得Set实例允许进行有意义的比较,即使他们的具体实现不同。两个集合实例相等(equal)如果它们包含相同的元素。

下面是Set接口的API实现:

public interface Set
extends Collection
{ // Basic operations int size(); boolean isEmpty(); boolean contains(Object element); // optional boolean add(E element); // optional boolean remove(Object element); Iterator
iterator(); // Bulk operations boolean containsAll(Collection
c); // optional boolean addAll(Collection
c); // optional boolean removeAll(Collection
c); // optional boolean retainAll(Collection
c); // optional void clear(); // Array Operations Object[] toArray();
T[] toArray(T[] a);}

Java平台提供了通用的Set实现:HashSet、TreeSet和LinkedHashSet。HashSet将元素存储在哈希表(hash table)中,它是最高效的Set实现,但是它无法确定迭代顺序。TreeSet将元素存储在红黑树中,元素按照值进行排序,它比HashSet稍慢。LinkedHashSet是HashSet的链表实现,它保持元素插入的顺序,但是访问性能比HashSet和TreeSet差。

这里有一个简单但是有用的Set使用场景。假设你有一个Collection c,你想创建另外一个Collection,但必须去除重复元素(只保留一个)。下面一行代码就实现了你的要求:

Collection
noDups = new HashSet
(c);

这里有另外一个变种实现,能保证原始集合中元素的顺序:

Collection
noDups = new LinkedHashSet
(c);

下面是一个泛化的封装了上面这行代码的方法:

public static 
Set
removeDups(Collection
c) { return new LinkedHashSet
(c);}

Set接口的基本操作

size方法返回Set中元素的数目。isEmpty方法判断Set是否为空。add方法往Set中添加指定元素,如果该元素不存在于集合中,并且返回一个布尔值标识元素是否成功添加。类似地,remove方法从Set中移除指定元素,如果该元素存在于集合中,并且返回一个布尔值标识是否成功移除。iterator方法返回Set的迭代器。

下面的程序接受一组单词作为参数args,打印出任何重复的单词、所有不重复单词的数目以及不重复单词列表。

import java.util.*;public class FindDups {    public static void main(String[] args) {        Set
s = new HashSet
(); for (String a : args) if (!s.add(a)) System.out.println("Duplicate detected: " + a); System.out.println(s.size() + " distinct words: " + s); }}

现在用下面的命令运行程序:

java FindDups i came i saw i left

程序输出如下:

Duplicate detected: iDuplicate detected: i4 distinct words: [i, left, saw, came]

注意上面的代码始终通过接口类型(Set)来引用对应的集合,而不是引用具体实现类型(HashSet)。这是强烈推荐使用的编程实践,因为这使得我们能更灵活地切换集合具体实现,只需要改变构造器函数。如果用来存储集合的变量或者用来传递给其他方法的参数被声明为集合具体实现类型而不是集合接口类型,那么这些变量或参数也必须随着具体实现的改变而改变。

前面例子中Set的具体实现类型是HashSet,它不能保证Set中元素的顺序。如果你想让程序按照字母顺序打印出单词,只需要把Set的具体实现类型从HashSet修改为TreeSet。仅仅修改前面一行代码:

Set
s = new TreeSet
();

将产生下面的输出:

java FindDups i came i saw i leftDuplicate detected: iDuplicate detected: i4 distinct words: [came, i, left, saw]

Set接口批量操作(bulk operation)

批量操作尤其适用于Set。当执行批量批量操作相当于执行集合代数意义上的运算。假设s1和s2都是Set。下面是各种批量操作:

  • s1.containsAll(s2) — 如果s2是s1的子集,返回true,否则返回false
  • s1.addAll(s2) — 得到的是s1和s2的并集
  • s1.retainAll(s2) — 得到的是s1和s2的交集
  • s1.removeAll(s2) — 得到的是s1和s2的差集(s1-s2,即所有s1中有但是s2中没有的元素的集合)

为了计算两个集合的并、交、差集而不修改这两个集合,调用者必须先拷贝一份,然后再调用bulk opertaion,比如下面:

Set
union = new HashSet
(s1);union.addAll(s2);Set
intersection = new HashSet
(s1);intersection.retainAll(s2);Set
difference = new HashSet
(s1);difference.removeAll(s2);

上面代码的结果集类型是HashSet。

让我们再次回顾之前的FindDups程序。假设你想知道哪些单词只出现一次,哪些单词出现不止一次,但是又不想重复打印单词。那么这种效果可以用两个Set来实现,一个Set包含参数列表中的所有单词,另外一个Set只包含重复出现的单词。那么只出现一次的单词就是这两个Set的差集。下面是代码实现:

import java.util.*;public class FindDups2 {    public static void main(String[] args) {        Set
uniques = new HashSet
(); Set
dups = new HashSet
(); for (String a : args) if (!uniques.add(a)) dups.add(a); // Destructive set-difference uniques.removeAll(dups); System.out.println("Unique words: " + uniques); System.out.println("Duplicate words: " + dups); }}

代码运行结果如下:

Unique words:    [left, saw, came]Duplicate words: [i]

还有一个不那么常见的集合代数操作,那就是对称集合差集 —— 由两个集合中的元素组成,但元素不能包含于两个集合的交集中。下面的代码实现了这种效果:

Set
symmetricDiff = new HashSet
(s1);symmetricDiff.addAll(s2); // 并集Set
tmp = new HashSet
(s1);tmp.retainAll(s2)); // tmp成了交集symmetricDiff.removeAll(tmp);

Set接口的数组操作

Set接口的数组操作与前面的Collection接口的数组操作没有任何不同。

转载地址:http://ewosi.baihongyu.com/

你可能感兴趣的文章
ubuntu自定义sourcelist
查看>>
ubuntu下安装VirtualBox增强包
查看>>
Virtualbox虚拟Ubuntu共享文件夹设置
查看>>
ubuntu下安装SSH
查看>>
ubuntu下修改/etc/hosts
查看>>
ubuntu在虚拟机下网卡丢失问题解决
查看>>
tar zxvf 什么意思?
查看>>
CentOS升级Python2.6到Python2.7并安装pip
查看>>
cqlsh执行报错"No appropriate python interpreter found."
查看>>
tomcat之三种部署方式
查看>>
a标签之下划线去掉css
查看>>
Mysql之取整函数
查看>>
ffmpeg之音频视频提取
查看>>
ffmpeg之视频合并
查看>>
ffmpeg之音频视频合成
查看>>
bat批处理之启动多个PC端微信
查看>>
bat批处理之统计脚本执行时间
查看>>
python之PyQt5安装timeout解决
查看>>
bat批处理之windows自动启动
查看>>
Maven之编码警告解决
查看>>