I am receiving a List of Strings that I am attempting to partition with .groupingBy()
, which will give me a Map<String, List<String>>
, and transform the Strings that are going to end up in the Lists that are in the Map.
Examples I've found use Collectors.mapping
which was what I thought to use, but all of the examples are using a method reference, like .mapping(SomeClass::getSomething, ...
which, since I'm acting on Strings, can't be done.
I thought I could use a lambda as the mapping function but can't seem to get the syntax right, ending up with "Type mismatch: cannot convert..." errors.
This illustrates the kind of thing I'm trying to do —
import java.util.*;
import java.util.stream.Collectors;
class Main
{
public static void main(String[] args)
{
List<String> inputs = Arrays.asList("D8", "S1", "S5", "D2", "D15", "S9");
System.out.println(inputs);
Map<String, List<String>>
outputs = inputs.stream()
.collect(
Collectors.groupingBy(s -> s.startsWith("D") ? "desperate" : "serious")
//,Collectors.mapping(n -> Integer.valueOf(n.replaceAll("[DS]", "")), Collectors.toList())
)
;
System.out.println(outputs);
}
}
This creates the Map, grouping the input data as I expect, and produces the output
{desperate=[D8, D2, D15], serious=[S1, S5, S9]}
but what I want, as you may guess from the commented out line
Collectors.mapping(n -> Integer.valueOf(n.replaceAll("[DS]", "")), Collectors.toList())
is a Map<String, List<Integer>>
containing the values extracted from the strings by removing the prefix.
My real use cases may transform one String to another String, or extract Integers from a more complex string, but this illustrates what I'm trying to do.
How can I use a lambda function to do the mapping when I'm groupingBy?
I'm also not clear on the use of the second argument toList()
in Collectors.mapping
from the examples I've read.
I have created a repl with this code.
Collectors.groupingBy()
has a version that takes another collector for the values, for example:
@Test
public void streamsTest() {
List<String> inputs = Arrays.asList("D8", "S1", "S5", "D2", "D15", "S9");
System.out.println(inputs);
Map<String, List<Integer>> outputs = inputs.stream()
.collect(
Collectors.groupingBy(
s -> s.startsWith("D") ? "desperate" : "serious",
Collectors.mapping(
s -> Integer.valueOf(s.substring(1)),
Collectors.toList())));
System.out.println(outputs);
}
This produces:
[D8, S1, S5, D2, D15, S9]
{desperate=[8, 2, 15], serious=[1, 5, 9]}