Guava源码阅读计划:base.Sets

union

传入:set1, set2

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

public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) {

  checkNotNull(set1, "set1");

  checkNotNull(set2, "set2");



  return new SetView<E>() {

    @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<E> iterator() {

      return new AbstractIterator<E>() {

        final Iterator<? extends E> itr1 = set1.iterator();

        final Iterator<? extends E> 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<E> stream() {

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

    }



    @Override

    public Stream<E> parallelStream() {

      return stream().parallel();

    }



    @Override

    public boolean contains(Object object) {

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

    }



    @Override

    public <S extends Set<E>> S copyInto(S set) {

      set.addAll(set1);

      set.addAll(set2);

      return set;

    }



    @Override

    public ImmutableSet<E> immutableCopy() {

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

    }

  };

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

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

在union内部重载中,依然是进行了懒操作,即只在需要时才进行iterator的遍历

 

filter

filter方法与Lists实现partition的方法需要注意的地方一样,即传入的时候有什么,传出的时候什么没了。

public static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) {

  if (unfiltered instanceof SortedSet) {

    return filter((SortedSet<E>) unfiltered, predicate);

  }

  if (unfiltered instanceof FilteredSet) {

    // Support clear(), removeAll(), and retainAll() when filtering a filtered

    // collection.

    FilteredSet<E> filtered = (FilteredSet<E>) unfiltered;

    Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);

    return new FilteredSet<E>((Set<E>) filtered.unfiltered, combinedPredicate);

  }



  return new FilteredSet<E>(checkNotNull(unfiltered), checkNotNull(predicate));

}

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

  • SortedSet
  • FilteredSet

这两个类都是内部类,并且都没有真正实现filter的功能,而只是进行一大堆的该有的重载和继承

其关键点在于FilteredSet类中,google在这里做了一个判断:如果是FilteredSet类,那么在进行filter时直接进行条件的再次叠加,不得不说,google在这一点上费劲心思

而SortedSet仅仅是为了继承SortedSet这个标签罢了

这样做达到了达到了两个效果:

  1. 实现懒操作,只有在整个流结束时才进行运算
  2. 对逻辑上判断做出交集,大大减少运算时的判断消耗

那么问题就来了,什么时候真正进行filter操作呢?哈哈哈,那些就直接交给已经写好的JDK collect父类吧。

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

  1. 尽可能的‘’懒’,即调用已有的类在更高层的类中进行操作,在底层仅做底层抽象和封装
  2. 尽可能的抽象,即在内部尽可能的调用高层的抽象类,再次进行抽象,一直到完成功能
  3. 尽可能的精细,即在该涉及到的问题上比如标签和多次filter上进行操作,尽可能的考虑到情况
  4. 大量使用泛型,静态内部类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值