Guava源码阅读——Collect包.Sets类

union类实现


传入:set1, set2

传出:内部实现的 setView 其继承了 AbstractSet

public static  SetView union(final Set set1, final Set set2) {

  checkNotNull(set1, "set1");

  checkNotNull(set2, "set2");



  return new SetView() {

    @Override

    public int size() {

      int size = set1.size();

      for (E e : set2) {

        if (!set1.contains(e)) {

          size++;

        }

      }

      return size;

    }



    @Override

    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

        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

    public Stream stream() {

      return Stream.concat(set1.stream(), set2.stream().filter(e -> !set1.contains(e)));

    }



    @Override

    public Stream parallelStream() {

      return stream().parallel();

    }



    @Override

    public boolean contains(Object object) {

      return set1.contains(object) || set2.contains(object);

    }



    @Override

    public > S copyInto(S set) {

      set.addAll(set1);

      set.addAll(set2);

      return set;

    }



    @Override

    public ImmutableSet immutableCopy() {

      return new ImmutableSet.Builder().addAll(set1).addAll(set2).build();

    }

  };

}
  1. Java所有的船餐都是引用,除了基本类型,final字段不允许引用被改变
  2. 静态方法的生命周期随着类的消亡而消亡
     

由这两点就可以知道,在union方法进行方法调用时,set1和set2会一直存在于SetView方法中,并且不会随着new申请空间而拷贝,因此set1、set2会一直存在并且随着外部的改变而改变。

在union内部重载中,只在需要时才进行iterator的遍历。

 

filter类的实现

filter和Lists类的partition方法实现需要注意的地方一样:传入的时候有什么 传出的时候就没有什么。


public static  Set filter(Set unfiltered, Predicate predicate) {
 
  if (unfiltered instanceof SortedSet) {
 
    return filter((SortedSet) unfiltered, predicate);
 
  }
 
  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 FilteredSet((Set) filtered.unfiltered, combinedPredicate);
 
  }
 
 
 
  return new FilteredSet(checkNotNull(unfiltered), checkNotNull(predicate));
 
}

观察这段源码,发现这个方法中涉及了两个类:

  • SortedSet
  • FilteredSet
     

这两个类都是内部类,并且都没有真正的实现filter的功能,而是进行了一大堆的重载、继承。最关键的是在FilteredSet类中,google做了一个判断:如果是FilteredSet类,那么在进行filter时直接进行条件的再次叠加。而SortedSet仅仅是继承SortedSet这个标签。这样做的好处:只在流程结束时进行运算,对逻辑上判断做出交集,大大减少运算时的判断消耗。

 

从以上两个类可以发现google在设计开发时的几个原则:

(1)尽可能的‘’懒’,即调用已有的类在更高层的类中进行操作,在底层仅做底层抽象和封装
(2)尽可能的抽象,即在内部尽可能的调用高层的抽象类,再次进行抽象,一直到完成功能
(3)尽可能的精细,即在该涉及到的问题上:比如标签和多次filter上进行操作,尽可能的考虑到情况
(4)大量使用泛型,静态内部类

 

 

 

 

你可能感兴趣的:(源码阅读)