Java 8中的流(Streams)用于HashMap

3

以下是我使用的地图,但当我运行时,我得到了声纳复杂度。如果不使用if else if else,我想使用Java 8 Stream。如何在Java 8 Streams中编写此代码...请给予建议。

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 (){
        .......
    }
 }

谢谢。

“但是当我运行时,我得到了声纳循环复杂度”,我不知道你想告诉我们什么。 - Holger
4个回答

2

使用Java 8,您可以进行行为参数化。这意味着您可以拥有一个具有2个属性的类(我们称之为X) - value(类型=String),method(类型=Function)

因此,您可以像这样构建Map:

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));

然后,您只需要迭代地图的entrySet(),并调用function.apply()函数即可。


谢谢!在我的情况下,“innerMap”和“outerMap”来自消费者应用程序插入的会话。所以我理解的是遍历地图,然后按上述方式添加一个类? - Sudheer
不要使用迭代,如果您对每种类型的键都有固定的处理程序方法,请定义一个处理程序接口,并创建一个枚举,其中包含每种类型键的特定实现处理程序。因此,您基本上不必编写if else来确定要为每个键类型调用哪个处理程序。 - shiladitya

0

你的if语句优先级决定了用于调用方法的关键值,因此,除非该优先级顺序已经定义好,否则可能没有更好的方法来完成你正在做的事情。

如果您要为每个键调用一个方法,则情况会有所不同,但else子句确保您仅为键ONE调用方法,即使地图中还有一个键TWO和一个键THREE


0
这是一个关于如何使用flatMap流式处理嵌套Map的示例。
我会将输入StringFunction之间的映射放在一个单独的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){ ... }

在上面的示例中,我使用了java.util.function.Consumer,它接受一个输入并返回void。如果您需要函数返回值,请改用java.util.function.Function

遍历整个映射并通过将键与常量进行比较来进行过滤是歪曲了“Map”概念。这就是为什么“Map”提供了像“get”或“containsKey”这样的方法的原因。这是因为可以使用实际映射实现的方式有效地实现这些操作。根据实现,它们具有“O(1)”或“O(log(n))”的时间复杂度,而您正在忽略它们并使用“O(n)”操作。 - Holger
@Holger 我认为你没有理解重点。我的示例代码展示了如何使用流来迭代Maps的示例。它并不展示解决这种类型问题的最佳代码。但那也不是问题所在。 - tomaj
Stack Overflow的主要目标是解决问题,而不是展示如何使用任意前提条件来完成某事,忽略永远不应该这样做的强有力理由。最起码应该在回答中提到不要这样做的原因。但更好的答案是“不要使用流,它们无法解决你的问题”。 - Holger
遍历地图并对其进行操作是完全有效的原因。有时,您会从第三方库中返回一个“Map”,并且您希望对地图中的每个条目执行操作。当某人在一年内寻找使用流与地图的方法时,可以查看我的解决方案并将其应用于他们的问题。这比仅仅说“永远不要这样做”更有用。 - tomaj
别开玩笑了。在StackOverflow上有大量的示例,展示了如何在Map上进行迭代当它有用时。没有人需要将“你的解决方案”放在有用的情境中。如果有人搜索如何使用流处理地图之类的内容,像这个那个这样的旧问题已经足够了。 - Holger

0

为什么不用这种方式呢?为什么需要流来实现这个功能?

 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));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接