3

I want to create a new map from the keyset() of an existing HashMap that maps a key to its index in the map.

Here's my attempt, which works:

Map<String, Integer> keysToIndex = new HashMap<>();
Integer index = 0;
for (String obj: hashMap.keySet()) {
    keysToIndex.put(obj, index);
    index += 1;
}

Does Java 8 provide features to create a map of each key's index, or is there a more idiomatic way to write this snippet?

Bohemian
  • 412,405
  • 93
  • 575
  • 722
Senthil Kumaran
  • 54,681
  • 14
  • 94
  • 131
  • See also http://stackoverflow.com/questions/17640754/zipping-streams-using-jdk8-with-lambda-java-util-stream-streams-zip – Alexis C. Feb 13 '16 at 19:05
  • Check also [this answer](http://stackoverflow.com/a/32864029/4856258) and other answers in that question. – Tagir Valeev Feb 14 '16 at 05:01

1 Answers1

3

Sets aren't ordered, so the "index" of an element in a Set is arbitrary (albeit unique). The "index" is simply the current size of the map, so you can use the result map's state to provide the index:

Map<String, Integer> keysToIndex = new HashMap<>();
hashMap.keySet().forEach(k -> keysToIndex.put(k, keysToIndex.size()));

This is more or less what your code is doing, but more compact since no extra variables or instructions are needed.

Incidentally, you can drop one more method call by using forEach() directly on the source map (and ignoring the value argument of the BiConsumer):

Map<String, Integer> keysToIndex = new HashMap<>();
hashMap.forEach((k, v) -> keysToIndex.put(k, keysToIndex.size()));
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Thanks!. I like both the calls. Btw, 'v' in second is unused. Is there any convention to denote the unused variable like `_`? Obviously, I could not use `_` when I tried it. – Senthil Kumaran Feb 13 '16 at 17:14
  • @SenthilKumaran I wondered the same thing, and thought of using `_` too (like other languages do), but [`_` is forbidden!](http://stackoverflow.com/questions/34521690/why-is-a-single-underscore-character-an-illegal-name-for-a-lambda-parameter). I use `ignore` or simply don't bother to telegraph non-use. – Bohemian Feb 13 '16 at 17:18
  • @Bohemian: the `_` identifier is forbidden because it might become exactly that placeholder for unused parameters in future Java version. Until then, nobody stops you from using `__` as identifier… – Holger Feb 15 '16 at 09:58
  • @Holger although as you may recall [Brian Goetz himself cautioned against using `__`](http://stackoverflow.com/questions/34521690/foo#comment56841233_34521690). IMHO the only single-byte character other than underscore that is reasonable candidate to mean "ignore" is `$`. For something more exotic, there's a single Japanese character `忽` (decimal 24573) that translates as "ignore" – Bohemian Feb 15 '16 at 18:09