Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't mapToInt be used with collect(toList())?

Tags:

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.

like image 895
Coder-Man Avatar asked May 27 '18 12:05

Coder-Man


People also ask

What does .collect collectors toList ()) do?

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.

What is collect() in Java?

Java Stream collect() performs a mutable reduction operation on the elements of the stream. This is a terminal operation.

What does. collect do in a Stream?

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.

Does a Stream store its elements?

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.


2 Answers

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);
like image 170
Eran Avatar answered Sep 17 '22 15:09

Eran


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.

like image 44
Mạnh Quyết Nguyễn Avatar answered Sep 20 '22 15:09

Mạnh Quyết Nguyễn