Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usage of function type congruent lambda expressions in Java 8

I struggle with the definition and usage of the

Stream.collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)

method in Java 8.

The method signature includes BiConsumer typed parameters. The BiConsumer FunctionalInterface defines one functional method accept(Object, Object). As far as I understand I can now use any lambda expression that is congruent to this functional interface.

But the example mentioned in the Stream.collect JavaDoc is e.g.

 List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

I do not understand why ArrayList.add(E e) (single parameter) is congruent with the BiConsumer.accept(T t, U u) method (two parameters) and can be used as the accumulator function in the collect method.

As you see I obviously have a lack of understanding and appreciate any explanation.

like image 967
FrVaBe Avatar asked Nov 11 '14 10:11

FrVaBe


2 Answers

The accumulator BiConsumer's two parameters are (1) the list itself and (2) the item to add to it. This:

List<String> asList = stringStream.collect(
    ArrayList::new,
    ArrayList::add,
    ArrayList::addAll
);

is equivalent to this:

List<String> asList = stringStream.collect(
    () -> new ArrayList<>(),
    (list, item) -> list.add(item),
    (list1, list2) -> list1.addAll(list2)
);

which will give the same result as this:

List<String> asList = stringStream.collect(
    new Supplier<ArrayList<String>>() {
        @Override
        public ArrayList<String> get() {
            return new ArrayList<>();
        }
    },

    new BiConsumer<ArrayList<String>,String>() {
        @Override
        public void accept(ArrayList<String> list, String item) {
            list.add(item);
        }
    },

    new BiConsumer<ArrayList<String>,ArrayList<String>>() {
        @Override
        public void accept(ArrayList<String> list1, ArrayList<String> list2) {
            list1.addAll(list2);
        }
    }
);
like image 197
Boann Avatar answered Sep 21 '22 19:09

Boann


ArrayList::add actually has 2 parameters. The ArrayList object on which you call the add method and the parameter to add.

ArrayList::add is equivalent to (list, element) -> list.add(element) and so it works as a BiConsumer

like image 24
Misha Avatar answered Sep 19 '22 19:09

Misha