简体   繁体   中英

Java 8 Streams for HashMap

Below is the Map I use , but when I run I get sonar cycolmatic complexity. instead of this if else if else.. I would like to use Java 8 Stream. How to write this in Java 8 Streams... Please advice.

Map<String, String> innerMap = new HashMap<String, String>();
innerMap.put("ONE" , "ABC");
innerMap.put("TWO" , "DEF");
innerMap.put("THREE" , "GHI");

Map<String, Map<String,String> outerMap = new HashMap<String, Map<String, String>>();
outerMap.put("OUTER" , innerMap);

if(outerMap.containsKey("OUTER")){
    if(innerMap.containsKey("ONE")){
        call one method.....
    }else if (innerMap.containsKey("TWO")){
        call one  method....
    }else if (){
        .......
    }
 }

Thanks.

With Java 8, you can have behaviour parameterization. That means you can have a class(let's call it X) with 2 attributes - value(type= String ), method(type= Function )

So, you can construct the Map like this:

Map<String, X> innerMap = new HashMap<>();
innerMap.put("ONE" , new X("ABC", SomeClass::somemethod));
innerMap.put("TWO" , new X("DEF", SomeClass::somemethod2));
innerMap.put("THREE" , new X("GHI", SomeClass::somemethod3));

And then, you can just iterate the entrySet() of the map, and just call the function.apply() ;

Your if statements priorities the key value that will be used to call a method, so unless that priority order is well-defined, there's probably no better way to do what you are doing.

It would be different if you were calling a method for each key present, but the else clause ensures that you're only calling the method for key ONE , even though there's also a key TWO and a key THREE in the map.

Here is an example on how to stream trough a nested Map using flatMap .

I would put the mappings between your input String and Function in a seperate Map.

public void withConsumerMap(){
    // Create a map of your functions too
    Map<String, Consumer<String>> functions = new HashMap<>();
    functions.put("ONE", this::one);

    Map<String, String> innerMap = new HashMap<>();
    innerMap.put("ONE" , "ABC");
    innerMap.put("TWO" , "DEF");
    innerMap.put("THREE" , "GHI");

    Map<String, Map<String,String>> outerMap = new HashMap<>();
    outerMap.put("OUTER" , innerMap);

    outerMap.entrySet().stream()
            .filter(outer -> outer.getKey().equals("OUTER"))
            .flatMap(outer -> outer.getValue().entrySet().stream())
            .forEach(inner -> functions.get(inner.getKey()).accept(inner.getValue()));
}

public void one(String param){ ... }

In the example above, I've used java.util.function.Consumer , which take one input, and returns void . If you need your functions to return something. Use java.util.function.Function instead.

Why not do it this way? Why do you need streams for this?

 Map<String, Runnable> executionPath = new HashMap<>();
    executionPath.put("OUTER-ONE", runnable1);
    executionPath.put("OUTER-TWO", runnable2);

    // I guess you want to pass the arg - such as "OUTER-ONE"

    executor.execute(executionPath.get(arg));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM