How to split a string into a map, grouping values by duplicate keys using streams?

北城余情 提交于 2021-02-19 07:24:27

问题


I want to convert the following

String flString="view1:filedname11,view1:filedname12,view2:fieldname21";

to a Map<String,Set<String>> to get the key/value as below:

view1=[filedname11,filedname12]
view2=[fieldname21]

I want to use Java 8 streams. I tried

Arrays.stream(tokens)
        .map(a -> a.split(":"))
        .collect(Collectors.groupingBy(
                a -> a[0], Collectors.toList()));

However the keys are also getting added to the value list.


回答1:


You should use a Collectors::mapping to map the array to an element.

String flString = "view1:filedname11,view1:filedname12,view2:fieldname21";

Map<String, List<String>> map = Pattern.compile(",")
    .splitAsStream(flString)
    .map(a -> a.split(":"))
    .collect(
        Collectors.groupingBy(a -> a[0],
            Collectors.mapping(a -> a[1], Collectors.toList())
        )
    );

map.entrySet().forEach(System.out::println);

Output

view1=[filedname11, filedname12]
view2=[fieldname21]



回答2:


You can use Collectors#toMap(keyMapper,valueMapper,mergeFunction) method as follows:

String flString = "view1:filedname11,view1:filedname12,view2:fieldname21";

Map<String, Set<String>> map = Arrays
        .stream(flString.split(","))
        .map(str -> str.split(":"))
        .collect(Collectors.toMap(
                arr -> arr[0],
                arr -> new HashSet<>(Set.of(arr[1])),
                (s1, s2) -> {
                    s1.addAll(s2);
                    return s1;
                }));

System.out.println(map);
// {view1=[filedname11, filedname12], view2=[fieldname21]}



回答3:


Off course @K.Nicholas solution with using downstream collector is perfect.

But I additionally created another alternative solution that also uses Stream API. It is more complex and generates three streams, but it works too.

String flString = "view1:filedname11,view1:filedname12,view2:fieldname21";

Map<String, Set<String>> map1 =
        Arrays.stream(flString.split(","))
                .map(a -> a.split(":"))
                .collect(Collectors.toMap(
                        a -> a[0],
                        a -> a[1],
                        (a1, a2) -> a1 + "," + a2))
                .entrySet().stream()
                .collect(Collectors.toMap(
                        e -> e.getKey(),
                        e -> Arrays.stream(e.getValue().split(","))
                                .collect(Collectors.toSet())));

map1.entrySet().forEach(System.out::println);



回答4:


You can achieve your goal using the following piece of codes:

String flString = "view1:filedname11,view1:filedname12,view2:fieldname21";
Map<String, List<String>> collect = Stream.of(flString)
        .flatMap(str -> Stream.of(str.split(",")))
        .map(keyValuePair -> keyValuePair.split(":"))
        .collect(Collectors.groupingBy(it -> it[0], Collectors.mapping(it -> it[1], Collectors.toList())));

Simple output:

{view1=[filedname11, filedname12], view2=[fieldname21]}


来源:https://stackoverflow.com/questions/66055002/how-to-split-a-string-into-a-map-grouping-values-by-duplicate-keys-using-stream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!