Java 8中将List<T>转换为Map<T, (index)>

4

有没有Java8中方便的流API方法可以将List<T>转换为Map<T, (index)>? 就像下面的例子一样:

    List<Character> charList = "ABCDE".chars().mapToObj(e->(char)e).collect(Collectors.toList());

    Map<Character, Integer> map = new HashMap<>();
    for (int i = 0; i < charList.size(); i++) {
        map.put(charList.get(i), i);
    }

map = {A=0, B=1, C=2, D=3, E=4}


1
Streams API 似乎严重缺少 zipWithIndex 操作。 - Marko Topolnik
不要认为这是重复的,但您可以使用类似于此的收集器:https://gist.github.com/lyubomyr-shaydariv/ab8ef4c00ed2e0e0ae9581af0f97f9b5 - Lyubomyr Shaydariv
@LyubomyrShaydariv:谢谢,看起来不错,但它比原来的复杂得多。目标是使其简单易读。 - Daniel Hári
1
在这个问题中,目标是迭代字符串中的字符,并显示它们的索引。但是Stream API没有很好的方法来创建一个包含字符及其索引的流,而链接的问题展示了如何以通用的方式实现:创建一个IntStream,然后可能调用mapToObj(或boxed())。 - Tunaki
这个 Map 的目的是什么? - Holger
显示剩余2条评论
1个回答

8
您可以使用以下不太优雅的技巧,但对于链接列表来说效率并不高:
List<String> list = Arrays.asList("a", "b", "c");
Map<String, Integer> result = 
    IntStream.range(0, list.size())
             .boxed()
             .collect(Collectors.toMap(list::get, Function.identity()));

在我看来,它也比简单的for循环不易读。因此,我会坚持使用简单的for循环。


或者完全跳过 List<String>,使用原始字符串,其中 String::charAt 是关键供应商。 - Mureinik
3
抱歉,那个不够清楚。List<String> 不相关。您可以在任何类型的列表上执行此操作。我的答案仅关注如何将列表转换为映射,而不涉及字符串字符。 - JB Nizet
我不明白为什么这被称为“恶毒的把戏”。这是基于索引操作的规范解决方案。 - Holger
@Holger 是的,但是遍历列表不应该是基于索引的操作:在非随机访问列表上非常低效。这也感觉很不自然,不应该从list.something()开始,而是从Intstream开始。 - JB Nizet
非自然的部分是由任务提供的,而任务出于某种原因依赖于索引。如果任务需要索引,则与流式传输元素相比,流式传输索引并不不自然。问题在于合并超出BMP范围的字符或代码点,但正如所说,这些问题已经存在于任务本身中,并且只是解决方案所继承的。 - Holger
我发现这个等效的 Kotlin 代码更自然,尽管我使用 Java 比 Kotlin 更多:https://gist.github.com/jnizet/39fe9e1801cb969143302491d8593678。 - JB Nizet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接