问题描述
我正在遍历一些String输入,试图将其转换为java 8 stream / lambdas,但遇到了一些问题。我的样板代码如下:
public static int count(List<String> list) {
String regex = "someRegexPatternHere"
Pattern p = Pattern.compile(regex);
int sum = 0;
for (String val: list) {
Matcher m = p.matcher(val);
if (m.find()) {
// summing logic here
}
}
return sum;
}
我正在尝试做类似的事情
list.stream()
.filter(i -> p.matcher(i).find())
.map(..............)
...
...但是无法得出汇总逻辑。谁能指出我正确的方向?
解决方法
您需要先应用matcher
,然后对find
进行过滤
return inputs.stream()
.map(p::matcher)
.filter(Matcher::find)
.map(m -> m.group(0))
.mapToInt(Integer::parseInt)
.sum();
使用lambda函数可以更清楚地看到它,但这是相同的
return inputs.stream().map(input -> p.matcher(input))
.filter(matcher -> matcher.find())
.map(m -> m.group(0))
.mapToInt(s -> Integer.parseInt(s)).sum();
,
由于Matcher
的逻辑,这是一个棘手的问题。我会这样写
list.stream()
.map(p::matcher)
.filter(Matcher::find)
.mapToInt(m -> Integer.parseInt(m.group(0))
.sum();
,
您非常亲密。用count()替换map(),该方法返回一个long。
long count = list.stream().filter(s -> p.matcher(s).find()).count();
,
只要您引用起源于java-8的Stream API功能(而不是特定版本本身),就让我为您介绍使用Java较新版本的方法。
Java 9 +
从Java的较新版本开始,您可以在Matcher
类上使用方法,直接返回结果流。
为匹配模式的输入序列的每个子序列返回匹配结果流。匹配结果的顺序与输入序列中匹配子序列的顺序相同。
Flatmap可以执行以下操作:
int sum = list.stream()
.map(p::matcher)
.flatMap(Matcher::results)
.mapToInt(mr -> Integer.parseInt(mr.group(0)))
.sum();
...或更短:
int sum = list.stream()
.flatMap(string -> pattern.matcher(string).results())
.mapToInt(mr -> Integer.parseInt(mr.group(0)))
.sum();