I wrote this code:
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String... args) {
List<String> a = Arrays.asList("One", "Two", "three");
List<Integer> lengths = a.stream().mapToInt(String::length).collect(Collectors.toList());
}
}
but it doesn't want to compile, saying:
Error:(8, 68) java: method collect in interface java.util.stream.IntStream cannot be applied to given types;
required: java.util.function.Supplier<R>,java.util.function.ObjIntConsumer<R>,java.util.function.BiConsumer<R,R>
found: java.util.stream.Collector<java.lang.Object,capture#1 of ?,java.util.List<java.lang.Object>>
reason: cannot infer type-variable(s) R
(actual and formal argument lists differ in length)
What's happening here? Why the limitation? If you use map. Instead of mapToInt, it works fine.
The toList() method of Collectors Class is a static (class) method. It returns a Collector Interface that gathers the input data onto a new list. This method never guarantees type, mutability, serializability, or thread-safety of the returned list but for more control toCollection(Supplier) method can be used.
Java Stream collect() performs a mutable reduction operation on the elements of the stream. This is a terminal operation.
The Stream. collect() is one of the Java 8's Stream API's terminal methods. It allows us to perform mutable fold operations (repackaging elements to some data structures and applying some additional logic, concatenating them, etc.) on data elements held in a Stream instance.
Sequence of elements: A stream provides an interface to a sequenced set of values of a specific element type. However, streams don't actually store elements; they are computed on demand.
mapToInt
produces an IntStream
, which doesn't have collect
method taking a single Collector
argument.
Since the end result is a List<Integer>
, you don't have to transform the Stream
to an IntStream
:
List<Integer> lengths = a.stream().map(String::length).collect(Collectors.toList());
Transforming the Stream
to an IntStream
would make sense if you want to collect the elements of the Stream
to an primitive array:
int[] lengths = a.stream().mapToInt(String::length).toArray();
If you want to transform to an IntStream
and still use the collect
method, you can write the following (which is less recommended):
List<Integer> lengths =
a.stream()
.mapToInt(String::length)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
After .mapToInt
you got an IntStream
.
The collect
definition for this stream is:
<R> R collect(Supplier<R> supplier,
ObjIntConsumer<R> accumulator,
BiConsumer<R, R> combiner);
Hence you cannot simply do toList()
here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With