gpt4 book ai didi

java - 使用流 groupingBy 时将字符串分组为多个组

转载 作者:行者123 更新时间:2023-12-05 08:35:45 24 4
gpt4 key购买 nike

我正在尝试做的一个简化示例:

假设我有一个字符串列表,需要根据是否包含特定子字符串的条件将其分为 4 组。如果一个字符串包含 Foo 它应该属于 FOO 组,如果它包含 Bar 它应该属于 BAR 组code>,如果它包含两者,则它应该出现在两个组中。

List<String> strings = List.of("Foo", "FooBar", "FooBarBaz", "XXX");

由于字符串被分组到第一个匹配组中,因此上述输入的简单方法无法按预期工作:

Map<String,List<String>> result1 =
strings.stream()
.collect(Collectors.groupingBy(
str -> str.contains("Foo") ? "FOO" :
str.contains("Bar") ? "BAR" :
str.contains("Baz") ? "BAZ" : "DEFAULT"));

结果1是

{FOO=[Foo, FooBar, FooBarBaz], DEFAULT=[XXX]}

期望的结果应该在哪里

{FOO=[Foo, FooBar, FooBarBaz], BAR=[FooBar, FooBarBaz], BAZ=[FooBarBaz], DEFAULT=[XXX]}

经过一段时间的搜索,我找到了另一种方法,它接近我想要的结果,但还不够完全

Map<String,List<String>> result2 =
List.of("Foo", "Bar", "Baz", "Default").stream()
.flatMap(str -> strings.stream().filter(s -> s.contains(str)).map(s -> new String[]{str.toUpperCase(), s}))
.collect(Collectors.groupingBy(arr -> arr[0], Collectors.mapping(arr -> arr[1], Collectors.toList())));

System.out.println(result2);

结果2是

{BAR=[FooBar, FooBarBaz], FOO=[Foo, FooBar, FooBarBaz], BAZ=[FooBarBaz]}

虽然这正确地将包含子字符串的字符串分组到所需的组中,但不包含子字符串并因此应属于默认组的字符串将被忽略。期望的结果如上所述(顺序无关紧要)

{BAR=[FooBar, FooBarBaz], FOO=[Foo, FooBar, FooBarBaz], BAZ=[FooBarBaz], DEFAULT=[XXX]}

现在我同时使用结果图并做了额外的事情:

result2.put("DEFAULT", result1.get("DEFAULT"));

以上是否可以一步完成?有没有比我上面的方法更好的方法?

最佳答案

这非常适合使用 mapMulti . MapMulti 需要一个 BiConsumer流式传输的值(value)消费者消费者 用于简单地将某些内容放回流中。这是添加到 Java 中的原因,因为 flatMaps 会产生不必要的开销。

这可以通过构建字符串数组来实现,就像您之前对 Token包含的字符串 所做的那样,并进行收集(也像您之前所做的那样)。如果在字符串中找到了键,则接受一个包含它和包含字符串的 String 数组。否则,接受一个带有默认键和字符串的字符串数组。

List<String> strings =
List.of("Foo", "FooBar", "FooBarBaz", "XXX", "YYY");
Map<String, List<String>> result = strings.stream()
.<String[]>mapMulti((str, consumer) -> {

boolean found = false;
String temp = str.toUpperCase();
for (String token : List.of("FOO", "BAR",
"BAZ")) {
if (temp.contains(token)) {
consumer.accept(
new String[] { token, str });
found = true;
}
}
if (!found) {
consumer.accept(
new String[] { "DEFAULT", str });
}
})
.collect(Collectors.groupingBy(arr -> arr[0],
Collectors.mapping(arr -> arr[1],
Collectors.toList())));

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

打印

BAR=[FooBar, FooBarBaz]
FOO=[Foo, FooBar, FooBarBaz]
BAZ=[FooBarBaz]
DEFAULT=[XXX, YYY]

请记住,流旨在让您的编码世界更轻松。但有时,只需要使用一些 Java 8 构造的常规循环即可。在学术练习之外,我可能会这样做。

Map<String,List<String>> result2 = new HashMap<>();

for (String str : strings) {
boolean added = false;
String temp = str.toUpperCase();
for (String token : List.of("FOO","BAR","BAZ")) {
if(temp.contains(token)) {
result2.computeIfAbsent(token, v->new ArrayList<>()).add(str);
added = true;
}
}
if (!added) {
result2.computeIfAbsent("DEFAULT", v-> new ArrayList<>()).add(str);
}
}

关于java - 使用流 groupingBy 时将字符串分组为多个组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73139610/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com