java8使用无用的组合器进行reduce

java8使用无用的组合器进行reduce,java,java-8,java-stream,reduce,Java,Java 8,Java Stream,Reduce,我需要将正则表达式列表应用于字符串,因此我想使用java8 map reduce: List<SimpleEntry<String, String>> list = new ArrayList<>(); list.add(new SimpleEntry<>("\\s*\\bper\\s+.*$", "")); list.add(new SimpleEntry<>("\\s*\\bda\\s+.*$", "")); list.add(n

我需要将正则表达式列表应用于字符串,因此我想使用java8 map reduce:

List<SimpleEntry<String, String>> list = new ArrayList<>();

list.add(new SimpleEntry<>("\\s*\\bper\\s+.*$", ""));
list.add(new SimpleEntry<>("\\s*\\bda\\s+.*$", ""));
list.add(new SimpleEntry<>("\\s*\\bcon\\s+.*$", ""));

String s = "Tavolo da cucina";

String reduced = list.stream()
    .reduce(s, (v, entry) -> v.replaceAll(entry.getKey(), entry.getValue()) , (c, d) -> c);
List List=new ArrayList();
添加(新的SimpleEntry(“\\s*\\bper\\s+.*$”,“”);
添加(新的SimpleEntry(“\\s*\\bda\\s+.*$”,“”);
添加(新的SimpleEntry(“\\s*\\bcon\\s+.*$”,“”);
字符串s=“Tavolo da cucina”;
String reduced=list.stream()
.reduce(s,(v,entry)->v.replaceAll(entry.getKey(),entry.getValue()),(c,d)->c);
实际上,这段代码可能不是很漂亮,但它是有效的。我知道这是无法并行的,对我来说是可以的


现在我的问题是:Java8(或更高版本)有没有可能写出更优雅的东西?我的意思是避免添加无用的组合器函数。

这里有另一个有趣的方法:将所有条目减少为函数组合,然后将组合函数应用于原始输入:

String result = list.stream()
        .map(entry -> 
            (Function<String, String>) text -> 
                       text.replaceAll(entry.getKey(), entry.getValue()))
        //following op also be written as .reduce(Function::compose) (see comment by Eugene)
        .reduce((f1, f2) -> f1.andThen(f2)) //compose functions
        .map(func -> func.apply(s)) //this basically runs all `replaceAll`
        .get();
String result=list.stream()
.map(条目->
(功能)文本->
text.replaceAll(entry.getKey(),entry.getValue())
//下面的op也可以写成.reduce(Function::compose)(参见Eugene的评论)
.reduce((f1,f2)->f1.然后(f2))//组合函数
.map(func->func.apply))//这基本上运行所有的'replaceAll'`
.get();

结果是您期望的字符串。虽然此函数组合不是直观的,但它似乎符合这样的想法,即原始列表实际上是一种“转换逻辑”链。

还有另一种有趣的方法:将所有条目减少为函数组合,然后将该组合函数应用于原始输入:

String result = list.stream()
        .map(entry -> 
            (Function<String, String>) text -> 
                       text.replaceAll(entry.getKey(), entry.getValue()))
        //following op also be written as .reduce(Function::compose) (see comment by Eugene)
        .reduce((f1, f2) -> f1.andThen(f2)) //compose functions
        .map(func -> func.apply(s)) //this basically runs all `replaceAll`
        .get();
String result=list.stream()
.map(条目->
(功能)文本->
text.replaceAll(entry.getKey(),entry.getValue())
//下面的op也可以写成.reduce(Function::compose)(参见Eugene的评论)
.reduce((f1,f2)->f1.然后(f2))//组合函数
.map(func->func.apply))//这基本上运行所有的'replaceAll'`
.get();

结果是您期望的字符串。虽然这个函数组合不是直观的,但它似乎符合这样的想法,即您的原始列表实际上是一种“转换逻辑”链。

受Oleksandr的评论和Holger的启发,我写了这篇文章

String reduced = list.stream()
.map(entry-> 
    (Function<String, String>) v -> v.replaceAll(entry.getKey(), entry.getValue()))
.reduce(Function.identity(), Function::andThen)
.apply(s);
String reduced=list.stream()
.map(条目->
(函数)v->v.replaceAll(entry.getKey(),entry.getValue())
.reduce(Function.identity(),Function::and then)
。申请;

这也将所有条目简化为一个函数组合。

受Oleksandr评论和Holger的启发,我写了这篇文章

String reduced = list.stream()
.map(entry-> 
    (Function<String, String>) v -> v.replaceAll(entry.getKey(), entry.getValue()))
.reduce(Function.identity(), Function::andThen)
.apply(s);
String reduced=list.stream()
.map(条目->
(函数)v->v.replaceAll(entry.getKey(),entry.getValue())
.reduce(Function.identity(),Function::and then)
。申请;

这也会将所有条目减少为一个函数组合。

@Eugene确实如此,
replaceAll
每次都返回一个新的
字符串。对不起,我的循环不够简单?如果不利用流的优点,如并行性、过滤等,为什么要涉及流呢?为什么不为(SimpleEntry:list){s=s.replaceAll(entry.getKey(),entry.getValue());}
?@Pshemo-yes,但这并不有趣:)。。。老实说,我只是在玩(和学习)java8流。
(c,d)->c
会给并行处理带来无效的结果,如果以
(c,d)->抛出新的断言错误(“不用于并行”)的形式抛出一个
异常会更好。
我发现了一个非常有趣的,由Holger编写的。@Eugene it,
replaceAll
每次都返回一个新的
字符串。对不起,我的循环不够简单?如果不利用流的优点,如并行性、过滤等,为什么要涉及流呢?为什么不为(SimpleEntry:list){s=s.replaceAll(entry.getKey(),entry.getValue());}
?@Pshemo-yes,但这并不有趣:)。。。老实说,我只是在玩(和学习)java8流。
(c,d)->c
会给并行处理带来无效的结果,如果以
(c,d)->抛出新的断言错误(“不用于并行”)
的形式抛出一个
异常更好。
(f1,f2)->f1.compose(f2)
可以替换为
Function::compose
,或者更好的
Function::然后
我猜
compose
之间的区别在于应用函数的顺序。如果你想在
g
之前做
f
,你必须使用
f,然后(g)
g.compose(f)
@ErnestKiwele另一个小问题是当你有一个空的
列表时,这可以写成
。reduce(Function::and then).orElse(Function.identity()).apply(s)我没有编译这个顺便说一句,只是看起来它会work@Holger对,
compose
将使函数从最后一个运行到第一个,但在这种情况下,这一切都无关紧要,因为所有
replaceAll
函数都将被执行,结果将是相同的。但是这是一个很好的观察结果,感谢
(f1,f2)->f1。compose(f2)
可以替换为
Function::compose
,或者更好的
Function::然后
我猜
compose
之间的区别在于函数的应用顺序。如果你想在
g
之前做
f
,你必须使用
f,然后(g)
g.compose(f)
@ErnestKiwele另一个小问题是当你有一个空的
列表时,这可以写成
。reduce(Function::and then).orElse(Function.identity()).apply(s)我没有编译这个顺便说一句,只是看起来它会work@Holger对,
compose
将使函数从最后一个运行到第一个,但在这种情况下这一切都无关紧要,因为