【问题标题】:Java 8 stream reduce MapJava 8 流减少映射
【发布时间】:2017-09-27 20:50:23
【问题描述】:

我有一个包含多个条目的 LinkedHashMap。我想在第一步中将多个条目减少为单个条目,然后将其映射到单个字符串。 例如: 我从这样的地图开始:

{"<a>"="</a>", "<b>"="</b>", "<c>"="</c>", "<d>"="</d>"}

最后我想得到一个这样的字符串:

<a><b><c><d></d></c></b></a>

(在这种情况下,字符串按顺序包含键,而不是按相反顺序包含值。但这并不重要,我想要一个通用的解决方案)

我想我需要map.entrySet().stream().reduce(),但是我不知道在reduce方法中要写什么,以及如何继续。

【问题讨论】:

  • 不清楚您所说的“将多个条目减少为一个”是什么意思。一个什么?一个入口?通用解决方案是什么意思?
  • 我想用一个函数将多个条目减少为一个条目。 reduce() 方法使用 BinaryOperator。在我的示例中,此 BinaryOperator 获取两个条目,连接两个键,并“反向连接”两个值。但我不知道如何实现它。 reduce() 也需要一个标识元素
  • 中间缩减条目的存在真的是一个要求吗?这与“我想要一个通用解决方案”的说法相矛盾。例如。你可以简单地使用String result = String.join("", map.keySet())+map.values().stream().reduce("", (a,b)-&gt;b+a);。如果您坚持使用单个 Stream 操作,则可以使用 String result = Stream.concat(map.keySet().stream(), map.values().stream().collect(ArrayDeque&lt;String&gt;::new, ArrayDeque::addFirst, (a,b) -&gt; b.descendingIterator().forEachRemaining(a::addFirst)).stream()) .collect(Collectors.joining()); 而无需构造 Map.Entry 实例。
  • 我没有考虑过 String.join 解决方案。第二种解决方案对我来说很难,我只是在学习流 API。但我非常喜欢它,所以我希望我能越来越了解它。不,不需要中间条目。

标签: java-8 java-stream


【解决方案1】:

由于您通过将键与键和值与值连接来减少条目,因此您要查找的标识是键和值都包含空字符串的条目。

String reduceEntries(LinkedHashMap<String, String> map) {
    Entry<String, String> entry =
        map.entrySet()
           .stream()
           .reduce(
               new SimpleImmutableEntry<>("", ""),
               (left, right) ->
                   new SimpleImmutableEntry<>(
                       left.getKey() + right.getKey(),
                       right.getValue() + left.getValue()
                   )
           );
    return entry.getKey() + entry.getValue();
}

Java 9 添加了一个静态方法 Map.entry(key, value) 用于创建不可变条目。

【讨论】:

  • 这是我想到的功能解决方案。不过可以使用一些解释。
  • 谢谢,应该这样做。我的主要问题是无法实例化条目。 SimpleImmutableEntry 应该可以解决问题。
  • 它给了我“lambda 表达式中不兼容的参数类型”
  • 在 jshell 中推断出 lambda 参数类型对我来说很好。您指定了哪些类型?
  • 我的错,我在我的代码中错过了一个菱形运算符,它导致了奇怪的错误。我真的很讨厌Java中的那个。如果您忘记了单个菱形运算符,您将花费数小时搜索问题。所有这些都是为了向后兼容非泛型库。
【解决方案2】:

这是一个关于我将如何做的例子:

import java.util.LinkedHashMap;

public class Main {

    static String result = "";

    public static void main(String [] args)
    {
        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
        map.put("<a>", "</a>");
        map.put("<b>", "</b>");
        map.put("<c>", "</c>");
        map.put("<d>", "</d>");

        map.keySet().forEach(s -> result += s);
        map.values().forEach(s -> result += s);

        System.out.println(result);
    }
}

注意:您可以先使用 ArrayUtils.reverse() 反转 values() 以获取 d

【讨论】:

  • 是的,这样做很容易,但我对流解决方案特别感兴趣。也许不是 reduce() 是合适的,也许是 Collectors.joining() 或 Collectors.reducing(),但我想在一个与流相关的语句中使用它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
  • 2016-04-08
  • 1970-01-01
  • 1970-01-01
  • 2015-02-01
  • 2017-12-04
  • 2015-02-11
相关资源
最近更新 更多