要映射的Java字符数组

aam*_*915 4 java java-8 java-stream

寻找一种方法将String转换为"char"=> int(index of)的映射.显然,这假设String具有唯一的字符.

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

String alphabet = "0123456789";
alphabet.chars().collect(Collectors.toMap(alphabet::charAt, Function.identity()));
Run Code Online (Sandbox Code Playgroud)

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

{c, i for i,c in enumerate("0123456789")}
Run Code Online (Sandbox Code Playgroud)

Spi*_*Pig 6

这有效.

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

编辑:

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


Mis*_*sha 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);
Run Code Online (Sandbox Code Playgroud)

如果你想要做重复检查像toMap不和仍然使用3个参数的形式,你将不得不更新这两个 2日(蓄电池)和第三(组合)的参数做了检查:

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!");})
        )
    );
Run Code Online (Sandbox Code Playgroud)

如你所见,这很难看,你可能想要定义一个辅助方法来简化这个.如果你愿意禁止并行流,你只能在累加器中检查重复项,但是你必须让组合器抛出异常:

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");}
);
Run Code Online (Sandbox Code Playgroud)

除非你这样做是为了锻炼,否则最好留下所有这些混乱toMap来处理.这就是它的用途.

  • @ aamit915小心你是怎么做的.我会更新我的答案. (2认同)
  • @TNT`Map :: putAll`是一个方法引用,相当于`(m1,m2) - > m1.putAll(m2)`.查看所有可能的方法引用表达式的JLS:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.13 (2认同)

Ole*_*ich 5

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

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

请注意,如果您有重复的字符,它将无法工作.

  • 因为`IntStream#collect`接受3个参数(`Supplier <R> supplier,ObjIntConsumer <R> accumulator,BiConsumer <R,R> combiner`),你需要使用.boxed()将它转换为`Stream <T>`可以接受`收藏家`. (3认同)