Java 8 Stream - How to return replace a strings co

2019-01-24 13:37发布

问题:

I wish to replace the code below using java8 .stream() or .foreach(). However I am having trouble doing this.

Its probably very easy, but I'm finding the functional way of thinking a struggle :)

I can iterate, no problem but the but returning the modified string is the issue due to mutability issues.

Anyone have any ideas ?

List<String> toRemove = Arrays.asList("1", "2", "3");
String text = "Hello 1 2 3";

for(String item : toRemove){
    text = text.replaceAll(item,EMPTY);
}

Thanks !

回答1:

Wow, you guys like doing things the hard way. this is what filter() and collect() are for.

List<String> toRemove = Arrays.asList("1", "2", "3");
String text = "Hello 1 2 3";

text = Pattern.compile("").splitAsStream(text)
    .filter(s -> !toRemove.contains(s))
    .collect(Collectors.joining());
System.out.println("\"" + text + "\"");

outputs (as the original code did)

"Hello   "

Of course, if your search strings are longer than one character, the previous method works better. If you have a tokenized string, though, split and join is easier.

List<String> toRemove = Arrays.asList("12", "23", "34");
String text = "Hello 12 23 34 55";
String delimiter = " ";

text = Pattern.compile(delimiter).splitAsStream(text)
    .filter(s -> !toRemove.contains(s))
    .collect(Collectors.joining(delimiter));
System.out.println("\"" + text + "\"");

outputs

"Hello 55"


回答2:

Since you can’t use the stream to modify the text variable you have to coerce the operation into one Function which you can apply to the text to get the final result:

List<String> toRemove = Arrays.asList("1", "2", "3");
String text = "Hello 1 2 3";
text=toRemove.stream()
             .map(toRem-> (Function<String,String>)s->s.replaceAll(toRem, ""))
             .reduce(Function.identity(), Function::andThen)
             .apply(text);


回答3:

text = toRemove.stream()
               .reduce(text, (str, toRem) -> str.replaceAll(toRem, ""));

would work for you.



回答4:

If I understood you correctly, you want to do something like this:

toRemove.forEach(removeString -> {
    text = text.replaceAll(removeString, "");
});

The only problem is, that you can't. :(

You can read about it here: http://javarevisited.blogspot.co.il/2014/02/10-example-of-lambda-expressions-in-java8.html

Section 6: One restriction with lambda expression is that, you can only reference either final or effectively final local variables, which means you cannot modified a variable declared in the outer scope inside a lambda.

EDIT

You can do something very ugly. Like this:

private static String text;

public void main (String[] args) {
    text = "Hello 1 2 3";
    List<String> toRemove = Arrays.asList("1", "2", "3");
    toRemove.forEach(removeString -> replaceTextWithEmptyString(removeString));
}

private static void replaceTextWithEmptyString(String whatToReplace) {
    text = text.replaceAll(whatToReplace, "");
}