You asked in comments how to do it with 3-argument IntStream#collect. Here it is:
Map<Character, Integer> map = IntStream.range(0, alphabet.length())
.collect(HashMap::new, (m, i) -> m.put(alphabet.charAt(i), i), Map::putAll);
If you want to do duplicate check like toMap does and still use the 3-argument form, you will have to update both 2nd (accumulator) and 3rd (combiner) arguments to do the check:
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!");})
)
);
As you see, this gets ugly and you would probably want to define a helper method to simplify this. If you are willing to disallow parallel stream, you can get away with only checking for duplicates in accumulator but then you will have to have the combiner throw an exception:
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");}
);
Unless you are doing this as an exercise, it's better to just leave all this mess for toMap to deal with. That's what it's there for.
'e'map to?Map<Character, Integer>is a very expensive data structure due to boxing. Do not use it in performance critical code. Consider e.g. goldman sachs collections instead (though conversion will be more expensive).enumeratein Python isn't cheaper either.