如何使用流将列表转换为具有索引的地图 - Java 8?

2022-09-01 00:47:32

我创建了一些方法,对字母表的每个字符进行计数。我正在学习流(函数式编程),并尝试尽可能多地使用它们,但在这种情况下我不知道该怎么做:

private Map<Character, Integer> numerateAlphabet(List<Character> alphabet) {
    Map<Character, Integer> m = new HashMap<>();
    for (int i = 0; i < alphabet.size(); i++)
        m.put(alphabet.get(i), i);
    return m;
}

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


答案 1

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

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

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


答案 2

最好使用代替,因为根据问题的答案:Function.identity()i->i

从当前的 JRE 实现开始,Function.identity() 将始终返回相同的实例,而每次出现标识符 -> 标识符时,不仅会创建自己的实例,甚至还会有一个不同的实现类。

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

推荐