如何使用stream - Java 8将List转换为使用索引的Map?

时间:2015-10-15 01:59:36

标签: java java-8 java-stream

我创建了计算字母表中每个字符的方法。我是学习流(函数式编程)并尝试尽可能多地使用它们,但在这种情况下我不知道如何做到这一点:

.gallery

那么,如何使用Java 8流重写它?

6 个答案:

答案 0 :(得分:36)

避免使用其他答案中提供的基于AtomicInteger的解决方案等有状态索引计数器。如果流是并行的,它们将失败。相反,流式传输索引:

IntStream.range(0, alphabet.size())
         .boxed()
         .collect(toMap(alphabet::get, i -> i));

上面假设传入列表不应该有重复的字符,因为它是一个字母表。如果您有可能重复元素,那么多个元素将映射到相同的键,然后您需要指定merge function。例如,您可以使用(a,b) -> b(a,b) ->a作为toMap方法的第三个参数。

答案 1 :(得分:12)

最好使用Function.identity()代替i->i

IntStream.range(0, alphabet.size())
                .boxed()
                .collect(toMap(alphabet::get, Function.identity()));

答案 2 :(得分:6)

在Java 8中使用带AtomicInteger的流:

private Map<Character, Integer> numerateAlphabet(List<Character> alphabet) {
    AtomicInteger index = new AtomicInteger();
    return alphabet.stream().collect(
            Collectors.toMap(s -> s, s -> index.getAndIncrement(), (oldV, newV)->newV));
}

答案 3 :(得分:1)

使用AtomicInteger

    AtomicInteger counter = new AtomicInteger();
    Map<Character, Integer> map = characters.stream()
            .collect(Collectors.toMap((c) -> c, (c) -> counter.incrementAndGet()));
    System.out.println(map);

答案 4 :(得分:1)

您可以将流收集到地图并将地图大小用作索引。

alphabet.stream()
    .collect(HashMap::new, (map, ch) -> map.put(ch, map.size()), Map::putAll);

答案 5 :(得分:0)

如果你在 Map 中有重复的值,你可以这样做

Map<Object, Deque<Integer>> result = IntStream.range(0, source.size()).boxed()
.collect(Collectors.groupingBy(source::get, Collectors.toList()));

或者如果您需要特定的 Map/List 实现,则像这样:

Map<Object, Deque<Integer>> result = IntStream.range(0, source.size()).boxed()
.collect(Collectors.groupingBy(source::get, IdentityHashMap::new, Collectors.toCollection(ArrayDeque::new)));