Reputation: 147
would like to know the difference on following methods, namely why two identical (identical by its logic) methods do not return the same expected result:
Method: create a Map of Character and List of Words:
void setMapping(List<String> words) {
Map<Character, List<String>> wordsByLetter = new HashMap<>();
for (String word : words) {
char letter = word.toLowerCase().charAt(0);
List<String> ref = wordsByLetter.get(letter);
if (ref == null) {
ref = new ArrayList<>();
wordsByLetter.put(letter, ref);
}
ref.add(word);
}
}
So in this case we make a reference to List of Strings called 'ref' and it will be updated each time we call method 'add' on it. Unfortunately, the same approach doesn't work with the second one:
2th Method: count all appearances:
void countCategories(List<String> categories) {
Map<String, Integer> mapper = new HashMap<>();
for (String category : categories) {
//need object Integer either to provide reference to it and to check whether it is a null
Integer counter = mapper.get(category);
if (counter == null) {
counter = 0;
//DOESN'T WORK THE SAME WAY:
//mapper.put(category, counter);
}
counter++;
mapper.put(category, counter);
}
}
So, my question is, why the second method doesn't work the same way as the first one, namely, why we cannot update counter in the particular Collection through object reference?
Upvotes: 2
Views: 46
Reputation: 393771
counter
is an object of the Integer
class, which means it is immutable. Therefore you cannot update its value.
counter++
returns a new Integer
instance and assigns it to the counter
variable. Therefore, if you call mapper.put(category, counter)
before counter++
, the original object referenced by counter
is stored in the HashMap
, and your counter++
statement has no effect on the contents of the HashMap
.
That's the reason why the following code doesn't work:
Integer counter = mapper.get(category);
if (counter == null) {
counter = 0;
mapper.put(category, counter);
}
counter++;
And instead, you have to write:
Integer counter = mapper.get(category);
if (counter == null) {
counter = 0;
}
counter++;
mapper.put(category, counter);
The first snippet, where you store ArrayList
s in the HashMap
is different, since ArrayList
is mutable, and calling add
for an ArrayList
already stored in the HashMap
mutates that ArrayList
.
Upvotes: 2
Reputation: 726479
The difference comes from mutability of map's value: List<String>
is mutable, while Integer
is immutable.
Your second code snippet can be fixed by adding an else
as follows:
if (counter == null) {
mapper.put(category, 1);
} else {
mapper.put(category, counter+1);
}
or an equivalent conditional expression with no if
mapper.put(category, (counter != null ? counter : 0) + 1);
Upvotes: 1