Chapters
Collector is a mutable reduction operation that accumulates input elements into a mutable result container, optionally transforming the accumulated result into a final representation after all input elements have been processed. Reduction operations can be performed either sequentially or in parallel.
The class Collectors provides implementations of many common mutable reductions. Aside from pre-built methods from Collectors class, we can create our own Collector method. Note that my explanation here is simplified. If you're planning to create your own
This example demonstrates Collector Interface methods like
In the example above, the form of
Next, let's create an example where the second form of
Note that the examples here are unsafe that may cause exceptions regarding raw types and object typecasting. Make sure to carefully build your Collector method. In this type of situation,
Collector Interface
Collector is a mutable reduction operation that accumulates input elements into a mutable result container, optionally transforming the accumulated result into a final representation after all input elements have been processed. Reduction operations can be performed either sequentially or in parallel.
The class Collectors provides implementations of many common mutable reductions. Aside from pre-built methods from Collectors class, we can create our own Collector method. Note that my explanation here is simplified. If you're planning to create your own
Collector
then, you need to read the documentation for full details.
This example demonstrates Collector Interface methods like
of()
, characteristics()
and finisher()
.
import java.util.stream.Collector; @SuppressWarnings({"unchecked"}) public class SampleClass{ public static void main(String[] args){ Collector c = Collector.of(StringBuilder::new, StringBuilder::append, (l,r) -> l.append(r.toString())); System.out.println("Characteristics"); System.out.println(c.characteristics()); StringBuilder builder = null; Object cont = c.supplier().get(); if(cont instanceof StringBuilder) builder = (StringBuilder)cont; else System.exit(1); c.accumulator().accept(cont, "String1-"); c.accumulator().accept(cont, "String2-"); c.accumulator().accept(cont, "String3"); Object s = c.finisher().apply(builder); System.out.println(s); } } Result Characteristics [IDENTITY_FINISH] String1-String2-String3In the example above, I used this form of
of()
method:static <T, R> Collector<T,R,R> of(Supplier<R> supplier, BiConsumer<R,T> accumulator, BinaryOperator<R> combiner, Collector.Characteristics... characteristics)
supplier
supplies our method with the specified container like StringBuilder, ArrayList, etc.accumulator
accumulates contents then put them to a container.combiner
combines two containers if two containers are in use. In the example above I only used one container. Thus, I didn't invoke combiner()
method.characteristics
is the characteristics of a Collector. There are three characteristics and you can read their description in the documentation.IDENTITY_FINISH
characteristic simply means that the Function
denoted by finisher
parameter behaves like Function.Identity().
In the example above, the form of
of()
doesn't have finisher
parameter. Although, I could still invoke a Function when I called the finisher()
. In this type of situation, java assigns IDENTITY_FINISH
characteristic to our Collector to infrom us that when we call finisher()
, it will behave like Function.Identity()
.
Next, let's create an example where the second form of
of()
is used.
import java.util.stream.Collector; @SuppressWarnings({"unchecked"}) public class SampleClass{ public static void main(String[] args){ Collector c = Collector.of(StringBuilder::new, StringBuilder::append, (l,r) -> l.append(r.toString()), Object::toString); System.out.println("Characteristics"); System.out.println(c.characteristics()); StringBuilder builder1 = null; Object cont1 = c.supplier().get(); StringBuilder builder2 = null; Object cont2 = c.supplier().get(); if(cont1 instanceof StringBuilder) builder1 = (StringBuilder)cont1; else System.exit(1); if(cont2 instanceof StringBuilder) builder2 = (StringBuilder)cont2; else System.exit(1); c.accumulator().accept(cont1, "String1-"); c.accumulator().accept(cont1, "String2-"); c.accumulator().accept(cont2, "String3-"); c.accumulator().accept(cont2, "String4"); Object combined = c.combiner().apply(cont1,cont2); StringBuilder result = null; if(combined instanceof StringBuilder) result = (StringBuilder)combined; else System.exit(1); Object s = c.finisher().apply(result); if(s instanceof String) System.out.println(s + " is a String"); } } Result Characteristics [] String1-String2-String3-String4 is a StringNext, let's put our
Collector
method in the collect() method of Stream class.
import java.util.stream.Collector; import java.util.HashSet; @SuppressWarnings({"unchecked"}) public class SampleClass{ public static void main(String[] args){ HashSet<String> hs = new HashSet<>(); hs.add("A"); hs.add("B"); hs.add("C"); hs.add("D"); Collector c = Collector.of(StringBuilder::new, (t,u) -> t.append("-"+u+"-"), (l,r) -> l.append(r.toString()), Object::toString, Collector.Characteristics.UNORDERED); System.out.println("Characteristics"); System.out.println(c.characteristics()); Object result = hs.stream().collect(c); System.out.println(result); } } Result Characteristics [UNORDERED] -A--B--C--D-
UNORDERED
characteristic indicates that the collection operation does not commit to preserving the encounter order of input elements. (This might be true if the result container has no intrinsic order, such as a Set.)
Note that the examples here are unsafe that may cause exceptions regarding raw types and object typecasting. Make sure to carefully build your Collector method. In this type of situation,
@SuppressWarnings({"unchecked"})
is necessary.
No comments:
Post a Comment