Reputation: 30037
I need to apply a list of regex to a string, so I thought to use 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);
Actually this code may be is not very beautiful, but it works. I know this cannot be parallelised and for me is ok.
Now my question is: is there any chance with Java8 (or higher version) to write something more elegant? I mean also avoiding to add the useless combiner function.
Upvotes: 0
Views: 232
Reputation: 30037
Inspired by Oleksandr's comment and Holger I wrote this
String reduced = list.stream()
.map(entry->
(Function<String, String>) v -> v.replaceAll(entry.getKey(), entry.getValue()))
.reduce(Function.identity(), Function::andThen)
.apply(s);
This also reduce all entries to a function composition.
Upvotes: 2
Reputation: 45309
Here's another, interesting approach: reduce all entries to a function composition, then apply that composed function on the original input:
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();
The result of this is your expected string. While this function composition is not intuitive, it nonetheless seems to fit the idea that your original list is in fact a sort of "transformation logic" chain.
Upvotes: 1