So I have this loop
for (Map.Entry<String, Integer> val : map.entrySet()) {
if (val.getValue() >= 10 && !Objects.equals(val.getKey(), " ") && val.getKey().length() > 3) {
stats = stats val.getKey().toLowerCase() " - " val.getValue() "\n";
}
}
Now I want to get rid of for loop and if condition using streams. How can I do this?
CodePudding user response:
Here could be an approach:
String stats = map.entrySet().stream()
// keep only the entries you're interested in:
.filter(entry -> entry.getKey().length() > 3 && entry.getValue() >= 10)
// serialise entries one by one:
.map(entry -> entry.getKey().toLowerCase() " - " entry.getValue())
// join:
.collect(Collectors.joining("\n"));
CodePudding user response:
To have a full use of stream functionalities You need to use stream, filter and reduce functions as follow:
// Get the stream from entrySet
String result = map.entrySet().stream()
// Filter entries based on your condition
.filter(val -> val.getValue() >= 10
&& !Objects.equals(val.getKey(), " ")
&& val.getKey().length() > 3)
// Apply the reduce to combine filtered entries in a single string
.reduce("", (stats, val) -> stats
val.getKey().toLowerCase()
" - "
val.getValue()
"\n");
The stream method applied to a Collection give a new Stream of the item present in the set:
Returns a sequential Stream with this collection as its source.
The filter method appplied on the stream:
Returns a stream consisting of the elements of this stream that match the given predicate.
The reduce function on the stream object:
Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value
CodePudding user response:
Good job using the forEach method. It's good practice to use streams and the stream API.
Here's a very simple program that does something similar to what you want to do.
import java.util.Map;
import java.util.HashMap;
public class Test {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("aaaa", 1);
map.put("bbbb", 2);
map.put("cccc", 3);
map.forEach((k,v)->System.out.println(k ": " v));
}
}
Now we can compile and run the code.
% javac Test.java
% java Test
aaaa: 1
bbbb: 2
cccc: 3
Now, what's the error in your code?
The error is this. The Map.forEach method takes a BiConsumer. The BiConsumer operation takes two input arguments (k and v) and returns no result. You are using a BiConsumer operation to return a result in a ternary expression. The BiConsumer operation has a return type of void. So what you can do is... you can execute code inside of the BiConsumer operation (like I did in my example) but you cannot return a result in the BiConsumer operation (which you are trying to do).
You can read about the Map.forEach method and the BiConsumer functional operation in the Java docs.