nikotromus
nikotromus

Reputation: 1064

Java 8 getOrDefault method on HashMap not working as expected

I cannot figure out why this hashmap routine is not adding up counts on my characters as expected. I suspect it has something to do with the cast between Character and char, but I'm not certain. The count is always 1 for every character.

String s = "loveleetcode";

Map<Character, Integer> hm = new HashMap<Character, Integer>(); 

for (int x = 0; x < s.length(); x++) {
    hm.put(s.charAt(x), hm.getOrDefault(hm.get(s.charAt(x)), 0) +1);
}

Upvotes: 1

Views: 3524

Answers (2)

Nikolas
Nikolas

Reputation: 44476

You use hm.get(s.charAt(x) it will always result in null because the entry key s.char(x) has not been put yet. Change it to:

hm.put(s.charAt(x), hm.getOrDefault(s.charAt(x), 0) + 1);

Moreover, I prefer a more self-explanatory approach using computeIfPresent and putIfAbsent:

hm.computeIfPresent(s.charAt(x), (ch, i) -> ++i); // if the key is present, increment the value
hm.putIfAbsent(s.charAt(x), 1);                   // if the key is not present, put with value 1

... or use Stream API and Collectors.groupingBy with Collectors.counting that is suitable for this kind of tasks:

Map<Character, Long> hm = s.chars().mapToObj(i -> (char) i)         // Stream<Character>
                                   .collect(Collectors.groupingBy(  // Map<Character, Long>
                                           Function.identity(),     // ... key is preserved
                                           Collectors.counting())); // ... total count

Upvotes: 0

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

I think you want to change the line;

hm.put(s.charAt(x), hm.getOrDefault(hm.get(s.charAt(x)), 0) +1);

to

hm.put(s.charAt(x), hm.getOrDefault(s.charAt(x), 0) +1);

In the original code hm.get(s.charAt(x)) will return null, and that key will not be present. Although the null is typed as an Integer, Map.getOrDefault (or indeed get) accepts Object for that argument, as that makes the Map interface work better with Java's bounded generics.

char can be autoboxed to Character just fine. Character can autounbox to char so long as it is not null.

Upvotes: 5

Related Questions