The architect means that get
and containsKey
have the same costs and may be accumulated into one check:
Integer val = map.get(c);
if (val != null) {
...
} else {
...
}
But I wonder why the architect is only concerned about that, as there are more things to improve:
- Refer to objects by their interfaces (Effective Java 2nd Edition, Item 52)
- Since Java 1.7 you can use the diamond operator <>
- Accumulate the autoboxing operations of the characters
- If you use
AtomicInteger
(or any other modifiable number class) instead ofInteger
you can even merge the get with one of the puts
So from my point of view the best performance, when using a HashMap, would offer:
Map<Character, AtomicInteger> map = new HashMap<>();
for (Character c : characters) {
AtomicInteger val = map.get(c);
if (val != null) {
val.incrementAndGet();
} else {
map.put(c, new AtomicInteger(1));
}
}
If the range of your characters is small (and known in advance), you could use an int array for counting. This would be the fastest of all possible solutions:
char firstCharacter="a";
char lastCharacter="z";
int[] frequency = new int[lastCharacter - firstCharacter + 1];
for (char c : characters) {
frequency[c - firstCharacter]++;
}