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的并集,返回的是一个不可修改的视图

guava源码阅读——collect.Sets类
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();
      }
    };
  }
View Code

 

3.2 intersection(final Set<E> set1, final Set<?> set2)方法

该方法是求两个set的交集,返回的仍是一个不可修改的视图

guava源码阅读——collect.Sets类
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;
     }
     //其余方法道理一致
    ......
   };
 }
View Code

 

3.3 difference(final Set<E> set1, final Set<?> set2)方法

该方法是求两个set的差集,返回一个不可修改的视图。
但是需要注意的一点是:如果该方法只会返回在set1中的值,不会返回set2中的,如果想要的差集结果希望是set1中的和set2中的,应该使用symmetricDifference方法。

guava源码阅读——collect.Sets类
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;
     }
     ......
   };
 }
View Code

 

3.4 filter方法

根据传入的set和过滤规则predicate,返回过滤后的set。

guava源码阅读——collect.Sets类
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));
 }
View Code
上一篇:打印一个数二进制位里面偶数和奇树的位数


下一篇:test