3

I am populating a Map<Character, Integer> alphabetToNumber which maps a letter corresponding to it alphabetical position

char [] alphabetArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
Map<Character, Integer> alphabetToNumber = new HashMap<>();
int counter = 1;
for(Character letter : alphabetArray) {
    alphabetToNumber.put(letter, counter);
    counter++;
}

The above code works but I was wondering if it can be done using Java 8 streams. Thanks.

bisarch
  • 1,388
  • 15
  • 31
  • take a look at this thread: https://stackoverflow.com/questions/20363719/java-8-listv-into-mapk-v – HBo Apr 16 '18 at 10:51
  • I saw that but I am not sure how I can use the variable `counter` and update it from a stream. – bisarch Apr 16 '18 at 10:55

5 Answers5

6
Map<Character, Integer> result = IntStream.rangeClosed('A', 'Z')
            .boxed()
            .collect(Collectors.toMap(
                    x -> (char) x.intValue(),
                    x -> x + (1 - 'A')));

Or even better with too much boxing/un-boxing:

Map<Character, Integer> result = IntStream.rangeClosed('A', 'Z')
    .collect(
        HashMap::new,
        (map, c) -> map.put((char) c, c + (1 - 'A')),
        HashMap::putAll
    );
Neuron
  • 5,141
  • 5
  • 38
  • 59
Eugene
  • 117,005
  • 15
  • 201
  • 306
3

You can use String.chars to get an IntStream, then just rely on the fact that char is really just an integer under the hood and do a bit of arithmetic.

Map <Character, Integer> alphabetToNumber = new HashMap<>();
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars()
    .forEach(ch -> alphabetToNumber.put((char) ch, ch - 'A' + 1));
Michael
  • 41,989
  • 11
  • 82
  • 128
2

You could use IntStream.range() to maintain the counter and use SimpleImmutableEntry to maintain for each letter the two information : letter and order.

char[] alphabetArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
Map<Character, Integer> alphabetToNumber =
        IntStream.range(0, alphabetArray.length)
                 .mapToObj(i -> new SimpleImmutableEntry<>(alphabetArray[i], i + 1))
                 .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
Neuron
  • 5,141
  • 5
  • 38
  • 59
davidxxx
  • 125,838
  • 23
  • 214
  • 215
2
char [] alphabetArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

        Map<Character, Integer> data = IntStream.range(0, alphabetArray.length).boxed()
        .collect(Collectors.toMap( x -> alphabetArray[x], x -> x +1));
mallikarjun
  • 1,862
  • 5
  • 23
  • 47
  • 1
    Why do you copy the `String` into a `char[]` array instead of just using `charAt(x)` on the `String` in your function? – Holger Apr 16 '18 at 12:07
  • I thought according to the question he/she is getting character array and it needs to convert into a map. – mallikarjun Apr 16 '18 at 13:07
  • I think, the problem description “mapping alphabets corresponding to their alphabetic position” of the question makes it clear that the array is not part of the task. The OP likely used the array because `for(char c: string)` doesn’t work (though that saving of source code characters doesn’t justify the runtime costs of copying an entire string). But in your code you’re streaming over indices anyway. – Holger Apr 16 '18 at 13:54
2
Map<Character, Integer> alphabetToNumber = new HashMap<>();
AtomicInteger atomicInteger = new AtomicInteger(0);
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars()
    .mapToObj(c -> (char) c)
    .forEach(c -> alphabetToNumber.put(c, atomicInteger.getAndIncrement()));
Alex Bondor
  • 326
  • 1
  • 9