0

I have a list of integers [1,2,3,4,5] and I want to convert it into a map after applying a multiplication function (*5) like this:

 {1 = 5, 2 = 10, 3 = 15, 4 = 20, 5 = 25}

I was able to use stream and use map function to perform the multiplication but I'm confused about how to convert the result into a map.

myList.stream().map(n -> n * 5).collect( ... )

Can someone please help.

user3828862
  • 63
  • 11
  • Don't apply the multiplication before mapping but apply it to the value extraction passed to the collector, e.g. `Collectors.toMap( v -> v, v -> v * 5)`. – Thomas May 06 '21 at 05:31

4 Answers4

5

Your current stream pipeline converts the original values to new values, so you can't collect it into a Map that contains both the original values and the new values.

You can achieve it if instead of map you use .collect(Collectors.toMap()) and perform the multiplication in toMap():

Map<Integer,Integer> map =
    myList.stream()
          .collect(Collectors.toMap(Function.identity(),
                                    n -> n * 5));

In you still want to use map, you can retain the original values by converting each of them to a Map.Entry:

Map<Integer,Integer> map =
    myList.stream()
          .map (n -> new SimpleEntry<> (n, n * 5))
          .collect(Collectors.toMap(Map.Entry::getKey,
                                    Map.Entry::getValue));
Eran
  • 387,369
  • 54
  • 702
  • 768
  • Thank you. Multiplication was actually the simplification of the problem. What if I have to call some function instead of multiplication. Can I still use - `myList.stream() .collect(Collectors.toMap(Function.identity(), someFunction()));` – user3828862 May 06 '21 at 05:34
  • @user3828862 of course, but it should probably be `n -> someFunction(n)` – Eran May 06 '21 at 05:38
  • Thank you for the response. Another question if you don't mind. If I want to return my struct like `{1={value=5}, 2={value=10), 3={value=15), 4={value=20), 5={value=25)}` i.e. Map One way to do it is I make my someFunction(n) return a map i.e. `{value = n*5}` Is there another way where I don't have to change my function someFunction(n) – user3828862 May 06 '21 at 05:55
  • @user3828862 I don't understand. Why would `someFunction(n)` return a `Map`? It should just return the value that should be mapped to `n`. – Eran May 06 '21 at 05:57
  • As I mentioned, If this is the output I'm looking for, `{1={"value"=5}, 2={"value"=10), 3={"value"=15), 4={"value"=20), 5={"value"=25)}` If `someFunction(n)` just returns a value called `output` then we how can we create `n = {"value" = output}` in `Collectors.toMap` – user3828862 May 06 '21 at 06:02
  • @user3828862 what is `{value=25}`? Is it a `Map`? What are the key and value of that `Map`? Should your output be a `Map>`? – Eran May 06 '21 at 06:05
2

You can use Collectors#toMap and pass any function for the value e.g. by using a UnaryOperator as shown below:

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        UnaryOperator<Integer> add = x -> x + 5;
        UnaryOperator<Integer> mutiply = x -> x * 5;
        UnaryOperator<Integer> factorial = x -> factorial(x);

        // Test
        List<Integer> list = List.of(1, 2, 3, 4, 5);
        Map<Integer, Integer> map1 = list.stream().collect(Collectors.toMap(Function.identity(), add));
        Map<Integer, Integer> map2 = list.stream().collect(Collectors.toMap(Function.identity(), mutiply));
        Map<Integer, Integer> map3 = list.stream().collect(Collectors.toMap(Function.identity(), factorial));

        System.out.println(map1);
        System.out.println(map2);
        System.out.println(map3);
    }

    static int getValue(int x, UnaryOperator<Integer> function) {
        return function.apply(x);
    }

    static int factorial(int x) {
        if (x <= 0) {
            return 1;
        }
        return x * factorial(x - 1);
    }
}

Output:

{1=6, 2=7, 3=8, 4=9, 5=10}
{1=5, 2=10, 3=15, 4=20, 5=25}
{1=1, 2=2, 3=6, 4=24, 5=120}
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0
Map<Integer, Long> map = Arrays
        .stream(nums)
        .boxed() // this
        .collect(Collectors.groupingBy(e -> e, Collectors.counting()));
Viktor Jovanovski
  • 1,513
  • 10
  • 26
0

The .collect(Collectors.toMap()) is what you need. Without the .map.

myList.stream().collect(Collectors.toMap(n-> n, n -> n * 5))

baumeister
  • 82
  • 5