Set接口
Set是一种Collection,为数学集合的抽象建模,仅继承Collection的方法,不能包含重复元素。Set 增强了equals 和 hashCode 的行为约束,允许Set实例进行有意义的比较,即使它们的实现不同。
Java平台包含三种Set实现: HashSet, TreeSet, and LinkedHashSet.
HashSet
, 元素储存在哈希表(hash table)中,性能最强,但是不保证元素的顺序。
TreeSet
, 元素存于红黑树(red-black tree)中, 基于元素的值排序,性能比HashSet慢很多。
LinkedHashSet
,元素储存于带链表的哈希表中, 元素顺序是元素插入的顺序, 代价比HashSet稍高。
获取一个Collection中的非重复元素:
Collection<Type> noDups = new HashSet<Type>(c);
// 如果保留顺序
Collection<Type> noDups = new LinkedHashSet<Type>(c);
JDK 8或以后, 可以简单的利用聚合操作生成一个Set:
c.stream()
.collect(Collectors.toSet()); // no duplicates
将Collection集合到 TreeSet:
Set<String> set = people.stream()
.map(Person::getName)
.collect(Collectors.toCollection(TreeSet::new));
泛型封装:
public static <E> Set<E> removeDups(Collection<E> c) {
return new LinkedHashSet<E>(c);
}
Set接口基本操作
size 返回元素个数。
isEmpty 判断是否为空,返回boolean值。
add 不存在时添加元素,返回boolean值,表明是否被添加。
remove 删除元素,返回boolean值,表明是否删除成功。
iterator 返回Iterator。
两个不同版本,聚合操作和for-each:
public class FindDups {
public static void main(String[] args) {
Set<String> distinctWords = Arrays.asList(args).stream()
.collect(Collectors.toSet());
System.out.println(distinctWords.size()+
" distinct words: " +
distinctWords);
}
}
// for-each
public class FindDups {
public static void main(String[] args) {
Set<String> s = new HashSet<String>();
for (String a : args)
s.add(a);
System.out.println(s.size() + " distinct words: " + s);
}
}
请注意,代码总是根据接口类型(Set)引用Collection,而不是根据其实现类型(HashSet,LinkedHashSet),这样可以仅改变构造函数灵活的改变实现。
仅通过集合的接口引用集合可以防止使用任何非标准操作。
Set接口批量操作
s1.containsAll(s2) — 返回boolean值,表明s2是否为s1的子集
s1.addAll(s2) — 把s1变成s1和s2的并集
s1.retainAll(s2) — 把s1变成s1和s2的交集
s1.removeAll(s2) — 把s1变成s1于s2的差集(包含于s1不包含与s2的集合)
无损计算并集,交集,差集,需要使用副本:
Set<Type> union = new HashSet<Type>(s1);
union.addAll(s2);
Set<Type> intersection = new HashSet<Type>(s1);
intersection.retainAll(s2);
Set<Type> difference = new HashSet<Type>(s1);
difference.removeAll(s2);
HashSet是最全面的Set实现。
找出句子中出现一次的单词和多次出现的单词:
public class FindDups2 {
public static void main(String[] args) {
Set<String> uniques = new HashSet<String>();
Set<String> dups = new HashSet<String>();
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);
}
}
对称差集,一个不太常用的集合,表示所有两个集合中不属于彼此交集的集合,即两个集合的并集减去两个集合的交集或两者并集于两者交集的差集。
Set<Type> symmetricDiff = new HashSet<Type>(s1);
symmetricDiff.addAll(s2);
Set<Type> tmp = new HashSet<Type>(s1);
tmp.retainAll(s2);
symmetricDiff.removeAll(tmp);