【问题标题】:java8 stream style to convert a key-value list to a map?java8流样式将键值列表转换为地图?
【发布时间】:2017-02-15 17:18:59
【问题描述】:

我想将 [k1, v1, k2, v2] 之类的列表转换为 {k1: v1, k2: v2} 之类的地图。原代码为:

List<Object> params = Arrays.asList("k1", "v1", "k2", "v2");
Map<String, Object> map = new HashMap<>();
for(int i = 0; i < params.size(); i+=2) {
    String key = (String)params.get(i);
    Object value = params.get(i + 1);
    map.put(key, value);
}
System.out.println(map); // => {k1=v1, k2=v2}

那我想把它转成java8流式吗?怎么样?

【问题讨论】:

  • 这种转变的目的是什么?
  • 只是为了学习。 @AndrewTobilko
  • 有一些库可以让这变得更容易,例如StreamEx
  • @PatrickParker, EntryStream.ofPairs 做了不同的事情:它创建了所有可能的配对。在这里你最终会得到k1=&gt;v1k1=&gt;k2k1=&gt;v2v1=&gt;k2v1=&gt;v2k2=&gt;v2
  • @PatrickParker,当然有办法:StreamEx.ofSubLists。如果您喜欢,请继续:StreamEx.ofSubLists(params, 2).toMap(list -&gt; (String)list.get(0), list -&gt; list.get(1)).

标签: functional-programming java-8 java-stream


【解决方案1】:

您可以使用它,但坦率地说,您的 for 循环更具可读性。我会尽量避免首先生成这样的列表,而是使用List&lt;SomePair&gt;,其中SomePair 包含键和值。

    List<Object> params = Arrays.asList("k1", "v1", "k2", "v2");
    Map<String, Object> map =
        IntStream.range(0, params.size() / 2)
                 .collect(HashMap::new,
                          (m, i) -> m.put((String) params.get(i * 2), params.get(i * 2 + 1)),
                          HashMap::putAll);

    System.out.println(map); // => {k1=v1, k2=v2}

【讨论】:

  • 或者,如果您首先通过boxed 进行管道传输,则可以使用Collectors.toMap.boxed().collect(Collectors.toMap(i -&gt; (String) params.get(i * 2), i -&gt; params.get(i * 2 + 1)))
【解决方案2】:

除了使用Stream 之外,您还可以使用旧的Iterator 并调用next 来获取下一个元素。当然,如果列表没有偶数个元素,这将失败。

Map<String, Object> map = new HashMap<>();
Iterator<Object> iter = params.iterator();
iter.forEachRemaining(x -> map.put((String) x, iter.next()));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多