public static void main(String args[]) { checkMap(new HashMap<>()); checkMap(new LinkedHashMap<>()); checkMap(new TreeMap<>()); } private static void checkMap(Map<Person, String> map) { System.out.println("Checking " + map.getClass()); Person ivan = new Person("Иван"); Person peter = new Person("Пётр"); Person maria1 = new Person("Мария"); Person maria2 = new Person("Мария"); map.put(ivan, ivan.name); map.put(peter, peter.name); map.put(maria1, maria1.name); map.put(maria2, maria2.name); // iterate and println for (Map.Entry<Person, String> entry : map.entrySet()) { System.out.println(entry); } // maria1.setName("Анна-Мария"); // maria2.setName("Анна-Мария"); System.out.println(map.get(maria1)); System.out.println(map.get(maria2)); System.out.println("==================================="); }
sobes.tech AI
Answer from AI
This code creates three different types of Map: HashMap, LinkedHashMap, and TreeMap, and inserts Person objects with the same names into each.
The key point is how Map determines the uniqueness of keys:
- HashMap and LinkedHashMap use the
hashCode()andequals()methods to compare keys. - TreeMap uses
compareTo()(or a Comparator) for sorting and comparing keys.
If the Person class does not override equals() and hashCode(), then for HashMap and LinkedHashMap, different objects with the same names will be considered different keys, and both will be stored in the Map.
TreeMap, if Person does not implement Comparable or a Comparator is not provided, will throw an error.
Example:
class Person {
String name;
Person(String name) { this.name = name; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person p = (Person) o;
return name.equals(p.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
Using such a class, HashMap and LinkedHashMap will consider maria1 and maria2 as the same keys, and the value for the second insertion will overwrite the first.
TreeMap requires Person to implement Comparable:
class Person implements Comparable<Person> {
String name;
// constructor
@Override
public int compareTo(Person other) {
return this.name.compareTo(other.name);
}
// overriding equals and hashCode is also recommended
}
Thus, the behavior of Map depends on the implementation of key comparison methods. If the name of the object is changed after insertion (uncommenting lines with setName), the keys in the Map may no longer be found correctly, as the hash or comparison order has changed, violating the Map contract.
Conclusion: for correct Map operation, keys should be immutable or fields involved in equals/hashCode/compareTo should not change after being placed in the Map.