programming

Java Streams: Collector Instead of Constructor

Let’s create a class that it stores a list of values and it can compute some value based on stored values. Internally elements are stored in a List. When class is created form the list of values, we can create a collector for it. There is no need for public constructor.


Constructor that accept the List class example

public class Bar<T> {
    List<T> list = new ArrayList<T>();

    public Bar(List<T> list) {
        this.list.addAll(list);
    }

    public void compute(){
        // some code
    }
}

Object Bar can be created with constructor call that accepts List object.

Bar<String> collect = new Bar<>(
            IntStream.range(1, 100)
                .mapToObj(x -> String.valueOf(x))
                .collect(Collectors.toList())
            );

Package visible constructor example

public class Foo<T> {
    List<T> list;

    Foo() {
        this.list = new ArrayList<T>();
    }

    public void compute(){
        // some code
    }
}

We create collector for Foo class. Collector is in the same package, so that it has access to Foo’s constructor.

public class FooCollector<T> implements Collector<T, List<T>, Foo<T>> {
    @Override
    public Supplier<List<T>> supplier() {
        return () -> new ArrayList<T>();
    }

    @Override
    public BiConsumer<List<T>, T> accumulator() {
        return (list, el) -> list.add(el);
    }

    @Override
    public BinaryOperator<List<T>> combiner() {
        return (listA, listB) -> {
            listA.addAll(listB);
            return listA;
        };
    }

    @Override
    public Function<List<T>, Foo<T>> finisher() {
        return (list) -> {
            Foo<T> foo = new Foo<>();
            foo.list.addAll(list);
            return foo;
        };
    }

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

Now we create Foo class from stream of values.

Foo<String> collect = IntStream.range(1, 100)
        .mapToObj(x -> String.valueOf(x))
        .collect(new FooCollector<>());

Leave a Reply