2014-11-14 2 views
1

Я пытаюсь создать реализацию Java 8 Collector для ImmutableList от Guava. Но я продолжаю получать странные ошибки нулевого указателя. Что не так с моим коллекционером?My ImmutableList Collector не работает?

java.lang.NullPointerException на java.util.stream.ReferencePipeline.collect (Unknown Source) в com.swa.rm.common.test.TestLauncher.main (TestLauncher.java:50)

это ошибка я получаю, когда я пытаюсь запустить этот код ...

ImmutableList.of (1,5,2,7,8,2,4) .stream(). фильтр (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); 
} 

} 

UPDATE :: Вот окончательная реализация, и, кажется, работает в настоящее время.

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); 
     } 

} 
+1

FYI, ваша окончательная реализация выглядит некорректной, так как ее 'поставщик()' возвращает тот же экземпляр 'ImmutableList.Builder', а не создает новый каждый раз. Это связано с несколькими проблемами, включая: A) компоновщик может быть добавлен из нескольких потоков одновременно, когда он не является потокобезопасным; B) 'combiner()' будет добавлять все элементы строителя к самому строителю; C) сам «Коллекционер» является состоятельным и не может быть повторно использован. – ColinD

+0

Да, я действительно понял это, и я переключил поставщика, чтобы каждый раз приносить новый экземпляр строителя, и избавляю вас от того, что он висит сверху как свойство. Я обновлю код выше, чтобы отразить это позже сегодня. – tmn

ответ

3

Ваша finisher() функция null; Я не уверен, чего вы ожидали.

+0

К сожалению, теперь я чувствую себя застенчивым. Не могу поверить, что я этого не замечал. – tmn