Home > Blockchain >  Iterating over hashmap with streams with condition
Iterating over hashmap with streams with condition

Time:06-29

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.

  1. Java docs for the Map.forEach method
  2. Java docs for the BiConsumer operation
  • Related