我发现了java 8流。
从地图开始我想从地图键中获取所有匹配的值。
我不明白为什么那个代码
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());
它给了我预期的结果
[005, 001, 003]
或使用时
datas.entrySet().stream()
.filter(entry -> {
...
})
.forEach(entry -> System.out.println(entry.getKey()));
它也给了我预期的结果
Value_005_1
Value_001_1
Value_003_1
[005, 001, 003]
答案 0 :(得分:3)
示例中没有终端操作:
datas.entrySet().stream()
.filter(entry -> { ...
和流由终端操作驱动(在终端操作存在之前不会执行任何操作)。这就是您的第二个示例有效的原因,因为您通过collect
或forEach
进行了终端操作。
除此之外,您违反了副作用的规则,基本上filter
不得在自身之外执行任何操作(例如您正在更新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());
答案 1 :(得分:1)
Java 8中的Streams有两种类型的操作,即中间操作和终端操作。
中间操作被懒惰地评估,这意味着,直到流以终端操作结束时才会执行它们。
终端操作适用于每个,收集,减少等。
您可以执行以下操作:
Stream createFilterStream(map,Predicate) {
return map.entryset.stream.filter(predicate)
}
不是实际的代码,但希望你能得到这个想法
方法的调用者可以按给定的谓词过滤地图,然后调用它上面的终端函数来使用结果
createFilterStream(map, predicate).collect(<collection_logic>)