我尝试使用流和收集器对值进行分组。我有一张要拆分的字符串列表。
我的数据:
List<String> stringList = new ArrayList<>();
stringList.add("Key:1,2,3")
stringList.add("Key:5,6,7")
key是map中的键,1,2,3是map中的值
首先,我尝试使用简单的 toMap
```
Map<String, List> outputKeyMap = stringList.stream()
.collect(Collectors.toMap(id -> id.split(":")[0],
id-> Arrays.stream(id.split(":")[1].split(",")).collect(Collectors.toList());
但它不起作用,因为它总是创建同一个键。所以我需要使用 `groupingBy` 功能。
Map<String, List> outputKeyMap = stringList.stream().collect(groupingBy(id -> id.toString().split(":")[0],
TreeMap::new,
Collectors.mapping(id-> Arrays.stream(id.toString().split(":")[1].split(","))
.map(Integer::valueOf)
.collect(Collectors.toSet()))));
但在这个解决方案中,编译器看不到传递到lambda函数中的值,我不知道为什么,因为 `Function` 是作为第一个参数,而且也是成 `Collectors.mapping` . 在此解决方案中,流不起作用。
Collectors.groupingBy (Function<? super T, ? extends K> classifier,
Supplier mapFactory,
Collector<? super T, A, D> downstream)
编辑:为什么groupingby函数不起作用
我忘了在collectors.mapping中添加collectors.toset()作为第二个参数。但后来我收到一套一套,所以这不是我要找的。应该使用flatmapping,但它是在java9中使用的。
Map<String, Set<Set>> collect = stringList.stream()
.collect(groupingBy(id -> id.split(":")[0],
TreeMap::new,
Collectors.mapping(id-> Arrays.stream(id.toString().split(":")[1].split(","),
Collectors.toSet())
2条答案
按热度按时间h9vpoimq1#
你必须使用超负荷的
Collectors.toMap
接受合并函数的:在这里
(l1, l2) -> { l1.addAll(l2); return l1; }
是合并函数。每当发生密钥冲突时,收集器就会调用它。作为List.addAll
对列表进行变异,我们需要确保创建的第一个列表是可变的,因此.collect(Collectors.toCollection(ArrayList::new))
在值Map器函数中。我还将第一次拆分优化为
Stream.map
在收集之前调用的操作,从而避免多次拆分。上述解决方案不会从列表中删除重复项。如果你需要的话,你应该收集到
Set
取而代之的是:请注意
LinkedHashSet
保留插入顺序。dohp0rv52#
假设源代码列表中没有重复的键,则可以
Map<String, List<Integer>>
比如:如果你有重复的钥匙,有一种方法
flatMapping
来自java9:输出将包含
Key
:{Key=[1, 2, 3, 5, 6, 7]}