guava源码阅读——collect.Sets类
Posted ericz2j
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了guava源码阅读——collect.Sets类相关的知识,希望对你有一定的参考价值。
1.写在前面
在开始之前,说明一下该篇中重点在union、intersection、difference、filter的实现,对于Sets类中的其他方法如newHashSet、newConcurrentHashSet、newLinkedHashSet等方法等见名知意,不做介绍。
2.阅读内容
collect.Sets类
3.源码分析
3.1 union(final Set<? extends E> set1, final Set<? extends E> set2)方法
该方法时求两个set的并集,返回的是一个不可修改的视图
public static SetView union(final Set set1, final Set set2) { //检查set1和set2是否为空 checkNotNull(set1, "set1"); checkNotNull(set2, "set2"); return new SetView() { @Override //求并集的大小,并集的大小肯定是大于等于set1或set2的大小,这里以set1大小为基数,依次去set2取元素判断是否包含在set1,不是size+1 public int size() { int size = set1.size(); for (E e : set2) { if (!set1.contains(e)) { size++; } } return size; } @Override //判断并集视图是否为空,需要满足set1和set2同时为空 public boolean isEmpty() { return set1.isEmpty() && set2.isEmpty(); } @Override //迭代 public UnmodifiableIterator iterator() { return new AbstractIterator() { final Iterator itr1 = set1.iterator(); final Iterator itr2 = set2.iterator(); @Override //迭代其中的一整个set(这里是set1),然后再去另一个set中迭代不重复的元素 protected E computeNext() { if (itr1.hasNext()) { return itr1.next(); } while (itr2.hasNext()) { E e = itr2.next(); if (!set1.contains(e)) { return e; } } return endOfData(); } }; } ...... @Override //判断是否包含一个元素,如果set1和set2任意一个包含,即包含 public boolean contains(Object object) { return set1.contains(object) || set2.contains(object); } @Override //将并集结果放入一个set,利用set元素不重复这条特性,直接添加即可 public > S copyInto(S set) { set.addAll(set1); set.addAll(set2); return set; } @Override //使用了建造者模式添加,返回一个不可变的set public ImmutableSet immutableCopy() { return new ImmutableSet.Builder().addAll(set1).addAll(set2).build(); } }; }
3.2 intersection(final Set<E> set1, final Set<?> set2)方法
该方法是求两个set的交集,返回的仍是一个不可修改的视图
public static SetView intersection(final Set set1, final Set set2) { //依旧是检查set checkNotNull(set1, "set1"); checkNotNull(set2, "set2"); return new SetView() { @Override public UnmodifiableIterator iterator() { return new AbstractIterator() { final Iterator itr = set1.iterator(); @Override //迭代set1,看set1中的每一个元素是否在set2中存在 protected E computeNext() { while (itr.hasNext()) { E e = itr.next(); if (set2.contains(e)) { return e; } } return endOfData(); } }; } ...... @Override //迭代set1,看set1中的每一个元素是否包含在set2中,是的话size+1 public int size() { int size = 0; for (E e : set1) { if (set2.contains(e)) { size++; } } return size; } //其余方法道理一致 ...... }; }
3.3 difference(final Set<E> set1, final Set<?> set2)方法
该方法是求两个set的差集,返回一个不可修改的视图。
但是需要注意的一点是:如果该方法只会返回在set1中的值,不会返回set2中的,如果想要的差集结果希望是set1中的和set2中的,应该使用symmetricDifference方法。
public static SetView difference(final Set set1, final Set set2) { checkNotNull(set1, "set1"); //检查 checkNotNull(set2, "set2"); return new SetView() { @Override public UnmodifiableIterator iterator() { return new AbstractIterator() { final Iterator itr = set1.iterator(); @Override //迭代set1,与set2比较,不包含返回,只看set1中的结果 protected E computeNext() { while (itr.hasNext()) { E e = itr.next(); if (!set2.contains(e)) { return e; } } return endOfData(); } }; } ...... @Override //也是只看set1中的结果 public int size() { int size = 0; for (E e : set1) { if (!set2.contains(e)) { size++; } } return size; } ...... }; }
3.4 filter方法
根据传入的set和过滤规则predicate,返回过滤后的set。
public static SortedSet filter(SortedSet unfiltered, Predicate predicate) { //根据传入的set类型选择过滤的逻辑方法 if (unfiltered instanceof FilteredSet) { // Support clear(), removeAll(), and retainAll() when filtering a filtered // collection. FilteredSet filtered = (FilteredSet) unfiltered; Predicate combinedPredicate = Predicates.and(filtered.predicate, predicate); return new FilteredSortedSet((SortedSet) filtered.unfiltered, combinedPredicate); } return new FilteredSortedSet(checkNotNull(unfiltered), checkNotNull(predicate)); }
以上是关于guava源码阅读——collect.Sets类的主要内容,如果未能解决你的问题,请参考以下文章
guava源码阅读——collect.ForwardingCollection类