[英]Iterating over hashmap with streams with condition
所以我有这个循环
for (Map.Entry<String, Integer> val : map.entrySet()) {
if (val.getValue() >= 10 && !Objects.equals(val.getKey(), " ") && val.getKey().length() > 3) {
stats = stats + val.getKey().toLowerCase() + " - " + val.getValue() + "\n";
}
}
现在我想摆脱 for 循环和使用流的 if 条件。 我怎样才能做到这一点?
这可能是一种方法:
String stats = map.entrySet().stream()
// keep only the entries you're interested in:
.filter(entry -> entry.getKey().length() > 3 && entry.getValue() >= 10)
// serialise entries one by one:
.map(entry -> entry.getKey().toLowerCase() + " - " + entry.getValue())
// join:
.collect(Collectors.joining("\n"));
方法有很多种,这里是一种。
Map<String, Integer> map = Map.of(" ", 18, "foo", 14, "abcd",
20, "ab", 10, "efgh", 3, "rstuv", 14);
然后我会定义一个Predicate<Entry<String, Integer>>
来减少流结构的混乱。 请注意,由于您正在检查length < 3
,因此可以省略单个空格的条件。 如果您的意思是检查一个空白字符串,您可以使用!val.getKey().isBlank()
作为条件。
reduce
接受一个初始参数,后跟一个BinaryOperator
作为累加器。 在这种情况下,累积是映射字符串的串联。 String::concat
满足要求,在这里用来完成操作。
Predicate<Entry<String, Integer>> check =
val -> val.getValue() >= 10
&& val.getKey().length() > 3;
然后只需流式传输EntrySet
即可。
String result = map.entrySet().stream().filter(check)
.map(e -> e.getKey().toLowerCase() + " - " + e.getValue() + "\n")
.reduce("", String::concat);
Systemm.out.print(result);
打印以下内容。
abcd - 20
rstuv - 14
要充分利用流功能,您需要使用流、过滤器和减少功能,如下所示:
// Get the stream from entrySet
String result = map.entrySet().stream()
// Filter entries based on your condition
.filter(val -> val.getValue() >= 10
&& !Objects.equals(val.getKey(), " ")
&& val.getKey().length() > 3)
// Apply the reduce to combine filtered entries in a single string
.reduce("", (stats, val) -> stats
+ val.getKey().toLowerCase()
+ " - "
+ val.getValue()
+ "\n");
应用于 Collection 的stream方法给出集合中存在的项目的新 Stream:
返回以此集合为源的顺序流。
应用于流的过滤方法:
返回由与给定谓词匹配的此流的元素组成的流。
流对象上的reduce函数:
使用提供的标识值和关联累积函数对此流的元素执行归约,并返回归约后的值
使用 forEach 方法做得很好。 使用流和流 API 是一种很好的做法。
这是一个非常简单的程序,它执行与您想做的类似的事情。
import java.util.Map;
import java.util.HashMap;
public class Test {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("aaaa", 1);
map.put("bbbb", 2);
map.put("cccc", 3);
map.forEach((k,v)->System.out.println(k + ": " + v));
}
}
现在我们可以编译并运行代码了。
% javac Test.java
% java Test
aaaa: 1
bbbb: 2
cccc: 3
现在,您的代码中的错误是什么?
错误是这样的。 Map.forEach 方法采用 BiConsumer。 BiConsumer 操作接受两个输入参数(k 和 v)并且不返回任何结果。 您正在使用 BiConsumer 操作以三元表达式返回结果。 BiConsumer 操作的返回类型为 void。 所以你可以做的是......你可以在 BiConsumer 操作中执行代码(就像我在我的示例中所做的那样),但你不能在 BiConsumer 操作中返回结果(你正在尝试这样做)。
您可以在 Java 文档中阅读有关 Map.forEach 方法和 BiConsumer 函数操作的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.