如何按列表描述的顺序有效处理HashMap?

Eas*_*ude 3 java sorting algorithm java-stream

这是我的问题:我有一个按时间顺序排列的事件名称列表,例如:

ArrayList<String> eventsOrder = new ArrayList<>(Arrays.asList("event1", "event2", "event3", "event4", "event5"));
Run Code Online (Sandbox Code Playgroud)

我有关于事件的数据的 HashMap,其中键是事件名称,例如:

HashMap<String, String> eventsData = new HashMap<>();
    eventsData.put("event2", "data2");
    eventsData.put("event1", "data1");
    eventsData.put("event3", "data3");
Run Code Online (Sandbox Code Playgroud)

我还有一个方法可以将来自 2 个事件的数据合并为 1 个:

public String merge(String previousEventsData, String nextEventsData);
Run Code Online (Sandbox Code Playgroud)

我需要按时间顺序将所有事件的数据合并到一个对象。所以在这种情况下,它会是这样的:

merge(merge("data1", "data2"),"data3");
Run Code Online (Sandbox Code Playgroud)

这就是我现在解决它的方法:

首先,这个 HashMap 可能包含也可能不包含所有事件的数据,所以我过滤了可用事件的名称:

ArrayList<String> eventsToProcess = eventsOrder.stream()
                .filter(eventName -> eventsData.containsKey(eventName))
                .collect(Collectors.toCollection(ArrayList::new));
Run Code Online (Sandbox Code Playgroud)

然后我使用这个丑陋的算法按时间顺序合并事件的数据:

    String finalData = "";

    int eventsCount = namesToProcess.size();

    finalData = eventsData.get(namesToProcess.get(0));
    if(eventsCount > 1) {
        for (int i = 1; i < eventsCount; i++){
            finalData = merge(finalData, eventsData.get(namesToProcess.get(i)));
        }

    }
Run Code Online (Sandbox Code Playgroud)

不是很优雅和可读,对吧?

问题:我将如何对 Java 流或递归函数进行相同的处理?

kay*_*ya3 6

像这样的东西应该是等​​效的,使用Stream.reduce

eventsOrder.stream()          // "event1", "event2", "event3", "event4", "event5"
    .map(eventsData::get)     // "data1", "data2", "data3", null, null
    .filter(Objects::nonNull) // "data1", "data2", "data3"
    .reduce(YourClass::merge) // merge(merge("data1", "data2"), "data3")
    .get()                    // gets the result from the Optional
Run Code Online (Sandbox Code Playgroud)

如果没有带有数据的事件,则该Optional.get方法抛出NoSuchElementException;在这种情况下,您的原始代码namesToProcess.get(0)将抛出IndexOutOfBoundsException。这应该是行为的唯一区别,假设您的eventsData地图没有任何null值。

  • @VishwaRatna 并不是每个二元运算都有一个标识,并且 OP 的“merge”方法没有被指定为具有标识。当期望代码总是产生结果并且没有结果表明编码错误时,调用不带保护的 .get() 是合适的;在这种情况下,您需要一条错误消息。鉴于OP的代码在这种情况下以同样的方式失败,我选择以保留失败条件的方式回答,但你会注意到,我在答案中指出了失败条件,以防OP不知道它。 (3认同)
  • 从 Java 10 开始,您可以使用“orElseThrow()”,它的作用与“get()”相同,但明确了不存在匹配元素时的行为。 (3认同)