user7128699 user7128699 - 25 days ago 9
Java Question

Not entirely clear on what this code does? (Includes Set, HashMap and .keySet())

So I've finished a program and have had help building it/worked with another person. I understand all of the program in terms of what each line of code does except one part. This is the code:

Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();
Map<String, Integer> stringIntegerMap1 = set1.stream().collect(HashMap::new,
(hashMap, s) -> hashMap.put(s, s.length()), HashMap::putAll);

stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));


Some background info:


  • getWordCut is a method that looks like this:

    public HashMap getWordCountsMap() {

    HashMap<String, Integer> myHashMap = new HashMap<String, Integer>();

    for (String word : this.getWordArray()) {
    if (myHashMap.keySet().contains(word)) {
    myHashMap.put(word, myHashMap.get(word) + 1);
    } else {
    myHashMap.put(word, 1);
    }

    }

    return myHashMap;
    }

  • firstWordGroup is a constructor that stores a string of words.



If anybody could explain exactly what this block of code does and how it does it then that would be helpful, thanks.

P.S: I'm not sure if supplying the whole program to reproduce the code is relevant so if you think it is, just leave a comment saying so and I will edit the question so you can reproduce the program.

Answer
Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();

This line calles getWordCountsMap which returns a map from words to their count. It then ignores the count and just takes the words in a set. Note this could be achieved in a lot of much simpler ways.

Map<String, Integer> stringIntegerMap1 = set1.stream()
    .collect(HashMap::new, (hashMap, s) -> hashMap.put(s, s.length()), HashMap::putAll);

This converts the set of words to a stream and then collects the stream. The collector starts by creating a hash map then, for each word, adding a map from the to its length. If multiple maps are created (as is allowed in streams) then they are combined using putAll. Again there are much simpler and clearer ways to achieve this.

stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));

This line iterates through all entries in the map and prints out the key and value.

All this code could have been achieved with:

Arrays.stream(getWordArray())
    .distinct().map(w -> w + ":" + w.length()).forEach(System.out::println);

This command converts the words to a stream, removes duplicates, maps the words to the output string then prints them.