【问题标题】:My ImmutableList Collector is not working?我的 ImmutableList 收集器不工作?
【发布时间】:2014-11-14 16:03:00
【问题描述】:

我正在尝试为 Guava 的 ImmutableList 构建 Java 8 Collector 实现。但我不断收到奇怪的空指针错误。我的收藏家怎么了?

java.lang.NullPointerException 在 java.util.stream.ReferencePipeline.collect(未知来源)在 com.swa.rm.common.test.TestLauncher.main(TestLauncher.java:50)

是我尝试运行此代码时收到的错误...

ImmutableList.of(1,5,2,7,8,2,4) .stream().filter(i -> i % 2 == 0) .collect(新的 ImmutableListCollector()) .forEach(i -> System.out.println(i));

调用这个收集器

package com.swa.rm.common.stream;

import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

import com.google.common.collect.ImmutableList;

public class ImmutableListCollector<T> implements Collector<T, ImmutableList.Builder<T>, ImmutableList<T>> {

 @Override
 public Supplier<ImmutableList.Builder<T>> supplier() {
  return ImmutableList::builder;
 } 

 @Override
 public BiConsumer<ImmutableList.Builder<T>, T> accumulator() {
  return (builder, t) -> builder.add(t);
 }

 @Override
 public BinaryOperator<ImmutableList.Builder<T>>  combiner() {
  return (left, right) -> { 
   left.addAll(right.build());
   return left;
  };
 }

 @Override
 public Function<ImmutableList.Builder<T>, ImmutableList<T>> finisher() {
  return null;
 }

 @Override
 public Set<Characteristics> characteristics() {
  return EnumSet.of(Characteristics.UNORDERED);
 }

}

更新:: 这是最终的实现,它现在似乎可以工作了。

import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

import com.google.common.collect.ImmutableList;

public class ImmutableListCollector<T> implements Collector<T, ImmutableList.Builder<T>, ImmutableList<T>> {


         @Override
         public Supplier<ImmutableList.Builder<T>> supplier() {
          return (() -> ImmutableList.builder());
         } 

         @Override
         public BiConsumer<ImmutableList.Builder<T>, T> accumulator() {
          return (builder, t) -> builder.add(t);
         }

         @Override
         public BinaryOperator<ImmutableList.Builder<T>>  combiner() {
          return (left, right) -> { 
           left.addAll(right.build());
           return left;
          };
         }

         @Override
         public Function<ImmutableList.Builder<T>, ImmutableList<T>> finisher() {
             return (b -> builder.build());
         }

         @Override
         public Set<Characteristics> characteristics() {
          return EnumSet.of(Characteristics.UNORDERED);
         }

}

【问题讨论】:

  • 仅供参考,您的最终实现看起来不正确,因为它的 supplier() 返回相同的 ImmutableList.Builder 实例,而不是每次都创建一个新实例。这样做有多个问题,包括:A)可以同时从多个线程添加构建器,但它不是线程安全的; B) combiner() 将把构建器的所有元素添加到构建器本身; C) Collector 本身是有状态的,不能重复使用。
  • 是的,我确实想通了,我每次都切换供应商以提供一个新的构建器实例,并摆脱了作为财产挂在顶部的那个。我将在今天晚些时候更新上面的代码以反映这一点。

标签: java lambda java-8 guava java-stream


【解决方案1】:

您的finisher() 函数是null;我不确定你的预期。

【讨论】:

  • 糟糕,现在我感到很尴尬。我不敢相信我忽略了这一点。
猜你喜欢
  • 2017-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 2013-03-13
相关资源
最近更新 更多