Java 8 Java8流-使用过滤器将元素添加到列表中
我正在发现Java8流 从映射开始,我想从映射键获取所有匹配的值 我不明白为什么会这样Java 8 Java8流-使用过滤器将元素添加到列表中,java-8,java-stream,Java 8,Java Stream,我正在发现Java8流 从映射开始,我想从映射键获取所有匹配的值 我不明白为什么会这样 Map<String,String> datas = new HashMap<String,String>(); datas.put("x1","123"); datas.put("x2","123"); datas.put("x3","123"); datas.put("Value_001_1","123"); datas.put(
Map<String,String> datas = new HashMap<String,String>();
datas.put("x1","123");
datas.put("x2","123");
datas.put("x3","123");
datas.put("Value_001_1","123");
datas.put("Value_001_2","123");
datas.put("Value_002_2","123");
datas.put("Value_003_1","123");
datas.put("Value_003_2","123");
datas.put("Value_004_2","123");
datas.put("Value_005_1","123");
datas.put("y1","123");
datas.put("y2","123");
datas.put("y3","123");
List<String> results = new ArrayList<String>();
String expression = "Value_#Position#_1";
Pattern pattern = Pattern.compile(expression.replaceAll("#Position#","(?<position>.*)"));
datas.entrySet().stream()
.filter(entry -> {
Matcher matcher = pattern.matcher(entry.getKey());
if(matcher.matches())
{
results.add(matcher.group("position"));
return true;
}
return false;
});
System.out.println(results);
但是当使用
datas.entrySet().stream()
.filter(entry -> {
...
})
.collect(Collectors.toList());
datas.entrySet().stream()
.filter(entry -> {
...
})
.forEach(entry -> System.out.println(entry.getKey()));
它给了我预期的结果
[005, 001, 003]
Value_005_1
Value_001_1
Value_003_1
[005, 001, 003]
或者当使用
datas.entrySet().stream()
.filter(entry -> {
...
})
.collect(Collectors.toList());
datas.entrySet().stream()
.filter(entry -> {
...
})
.forEach(entry -> System.out.println(entry.getKey()));
这也给了我预期的结果
[005, 001, 003]
Value_005_1
Value_001_1
Value_003_1
[005, 001, 003]
示例中没有终端操作:
datas.entrySet().stream()
.filter(entry -> { ...
并且流由终端操作驱动,在终端操作出现之前,不会执行任何操作。这就是为什么第二个示例有效,因为您有一个通过collect或forEach的终端操作
除此之外,您违反了一条关于副作用的规则,基本上,过滤器不能像您更新ArrayList那样执行自身之外的任何操作
和往常一样,霍尔格找到了一个更好的方法:
Pattern pattern = Pattern.compile("Value_(\\d+)_1");
List<String> results = datas.keySet().stream()
.map(pattern::matcher)
.filter(Matcher::matches)
.map(m -> m.group(1))
.collect(Collectors.toList());
Java8中的流有两种类型的操作,中间操作和终端操作 中间操作被惰性地评估,这意味着,直到流以终端操作结束时,它们才被执行 终端操作是forEach、collect、reduce等 您可以执行以下操作:
Stream createFilterStream(map,Predicate) {
return map.entryset.stream.filter(predicate)
}
不是实际的代码,但希望您能理解
方法的调用方可以根据给定的谓词过滤映射,然后调用映射上的terminal函数来使用结果
createFilterStream(map, predicate).collect(<collection_logic>)
谢谢你的链接。好的,我想我明白了。关于你的最后一句话,有没有一种更好的、不违反副作用规则的方法来做这项工作?@tweetysat你可以这样做,例如:List results=datas.keySet.stream.filterx->x.matchesValue\ud+\u 1.mapx->x.replaceFirstValue\ud+\u 1,$1.collectors.toList@tweetysat或只应用一次正则表达式列表results=datas.keySet.stream.mapx->{Matcher m=pattern.matcherx;if m.matches{return m.group1;}return;}.filterx->!x、 isEmpty.collectors.toList@Eugene:不需要引入空字符串,只需稍后对其进行过滤:List results=datas.keySet.stream.mappattern::matcher.filterMatcher::matches.mapm->m.group1.collectCollectors.toList@霍尔格太棒了!我有点倾向于这样,但找不到合适的词语。谢谢你