要映射的Java字符数组

时间:2015-04-19 01:38:19

标签: java java-8 java-stream

寻找将String转换为“char”=>的地图的方法int(索引)。显然,这假设String具有唯一的字符。

有没有办法用Streams做到这一点?我认为这会有效,但是在尝试编译它时遇到了错误:

String alphabet = "0123456789";
alphabet.chars().collect(Collectors.toMap(alphabet::charAt, Function.identity()));

基本上我想要一些与Python代码相同的东西:

{c, i for i,c in enumerate("0123456789")}

4 个答案:

答案 0 :(得分:6)

这很有效。

Map<Integer, Character> map =
  IntStream.range(0, alphabet.length()).boxed()
           .collect(Collectors.toMap(x -> x, alphabet::charAt));

编辑:

当然,如果你使用Scala(也在JVM上运行),你可以写得更短。那就是alphabet.zipWithIndex.toMap

答案 1 :(得分:6)

您在评论中询问如何使用3参数IntStream#collect进行操作。这是:

Map<Character, Integer> map = IntStream.range(0, alphabet.length())
    .collect(HashMap::new, (m, i) -> m.put(alphabet.charAt(i), i), Map::putAll);

如果你想像toMap那样进行重复检查并且仍然使用3参数形式,则必须更新 第2(累加器)和第3(组合器)参数做检查:

map = IntStream.range(0, alphabet.length())
    .collect(
        HashMap::new, 
        (m, i) -> m.merge(alphabet.charAt(i), i, 
            (a,b) -> {throw new IllegalStateException("duplicate!");}
        ), 
        (m1, m2) -> m2.forEach((c,i) -> 
            m1.merge(c, i, (a,b) -> {throw new IllegalStateException("duplicate!");})
        )
    );

如您所见,这变得很丑陋,您可能希望定义一个辅助方法来简化此操作。如果你愿意禁止并行流,你只能在累加器中检查重复项,但是你必须让组合器抛出异常:

map = IntStream.range(0, alphabet.length())
    .collect(
            HashMap::new, 
            (m, i) -> m.merge(alphabet.charAt(i), i, 
                (a,b) -> {throw new IllegalStateException("duplicate!");}
            ), 
            (m1, m2) -> {throw new AssertionError("parallel not allowed");}
);

除非你做这个练习,否则最好留下所有这些混乱的toMap来处理。这就是它的用途。

答案 2 :(得分:5)

这会创建一个从每个字符到其整数的映射:

Map<Character, Integer> map = IntStream.range(0, alphabet.length())
    .boxed().collect(Collectors.toMap(alphabet::charAt, Function.identity()));

请注意,如果您有重复的字符,它将无效。

答案 3 :(得分:0)

正如您在此处发布的各种解决方案中所看到的那样,stream()并不能让事情变得更加轻松。

虽然功能风格的意大利面条代码现在风靡一时,但我建议使用命令式编程来提高可读性。

for(int i=0; i<s.length(); i++) map.put(s.charAt(i), i);

说真的,程序有时会好得多!人们低估了程序代码的清晰度及其效率。

但是,您可能希望在您的方案中使用此代码:

if (c<'0' || c>'9') throw RuntimeException("Not a digit");
int digit = c - '0';

Map更便宜(更快,0内存)。