美文网首页
Guava使用的经验和教训

Guava使用的经验和教训

作者: 缄默的石头 | 来源:发表于2018-08-16 17:14 被阅读17次

    Guava使用的经验和教训

    1.com.google.common.collect.Lists#transform(List<T> originList,Function function)
    由于Lists.transform是延迟调用,返回的其实是originList的view,也就是当客户端遍历生成的列表时,给定的Function应用到originList的元素上,而且每一次遍历生成的列表都会重新应用一次。
    

    核心代码

    @Override
        public Iterator<T> iterator() {
          return listIterator();
        }
    
        @Override
        public ListIterator<T> listIterator(int index) {
          return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
            @Override
            T transform(F from) {
              return function.apply(from);
            }
          };
        }
    
    错误的使用场景
    1. 通过线程池执行Callable任务,任务的返回结果是通过Lists.transform来完成的

    错误代码示例

    @Override
        public List<XXX> call() {
            return Lists.transform(Safes.of(list), new Function<P, XXX>() {
    
                @Override
                public ResultWrapper<R> apply(P input) {
                    return fun.apply(input);
                }
            });
        }
    

    通常我们的使用场景是在主线程中创建任务,然后将任务提交到ThreadPool中,然后获取Future,在主线程中调用Future.get(),然后处理结果。但是由于上述的错误示例,发现代码的逻辑并没有并行执行,而是拿到结果后在遍历的串行执行的,这个就是因为Lists.transform的惰性调用导致并行化失败。

    2.对Lists.transform的结果进行二次处理,然后执行集合求交集、差集等涉及到equals的操作

    错误代码示例

    List<XXX> result = Lists.transform();
    List<XXX> subList = Lists.newArrayList();
    for(XXX x:result){
        if(true){
            subList.add(x);
        }
    }
    result = CollectionUtils.substract(result,subList);
    

    然后会发现没有任何元素被移除,前提条件是XXX没有重写equals方法。

    解决方法

    问题的原因就是因为惰性加载导致的,所以如果Lists.transform后,可以对结果集进行一次copy(To avoid lazy evaluation when the returned list doesn't need to be a view, copy the returned list into a new list of your choosing.)

    相关文章

      网友评论

          本文标题:Guava使用的经验和教训

          本文链接:https://www.haomeiwen.com/subject/iiuobftx.html