Основной причиной переопределения функции equals () в большинстве случаев является проверка на наличие дубликатов в определенных коллекциях. Например, если вы хотите использовать Set для содержания созданного вами объекта, вам необходимо переопределить equals () и hashCode () внутри вашего объекта. То же самое применимо, если вы хотите использовать свой пользовательский объект в качестве ключа на карте.
Это очень важно, так как я видел, как многие люди на практике допускают ошибку, добавляя свои пользовательские объекты в Sets или Maps без переопределения equals () и hashCode (). Причина, по которой это может быть особенно коварным, заключается в том, что компилятор не будет жаловаться, и вы можете получить несколько объектов, которые содержат одинаковые данные, но имеют разные ссылки в коллекции, которая не допускает дублирования.
Например, если у вас был простой компонент с именем NameBean с одним атрибутом String 'name', вы могли бы создать два экземпляра NameBean (например, name1 и name2), каждый с одним и тем же значением атрибута 'name' (например, "Alice"). ). Затем вы можете добавить и name1, и name2 в набор, и набор будет размером 2, а не размером 1, что и предполагается. Аналогично, если у вас есть Map, например Map, для сопоставления бина имени с каким-либо другим объектом, и вы сначала сопоставили name1 со строкой «first», а затем сопоставили name2 со строкой «second», у вас будут обе пары ключ / значение. на карте (например, name1 -> "first", name2 -> "second"). Поэтому, когда вы выполняете поиск по карте, он вернет значение, сопоставленное с точной ссылкой, которую вы передаете, которая является либо name1, name2, либо другой ссылкой с именем «Alice», которая вернет null.
Вот конкретный пример, которому предшествует результат его запуска:
Выход:
Adding duplicates to a map (bad):
Result of map.get(bean1):first
Result of map.get(bean2):second
Result of map.get(new NameBean("Alice"): null
Adding duplicates to a map (good):
Result of map.get(bean1):second
Result of map.get(bean2):second
Result of map.get(new ImprovedNameBean("Alice"): second
Код:
// This bean cannot safely be used as a key in a Map
public class NameBean {
private String name;
public NameBean() {
}
public NameBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
// This bean can safely be used as a key in a Map
public class ImprovedNameBean extends NameBean {
public ImprovedNameBean(String name) {
super(name);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if(obj == null || getClass() != obj.getClass()) {
return false;
}
return this.getName().equals(((ImprovedNameBean)obj).getName());
}
@Override
public int hashCode() {
return getName().hashCode();
}
}
public class MapDuplicateTest {
public static void main(String[] args) {
MapDuplicateTest test = new MapDuplicateTest();
System.out.println("Adding duplicates to a map (bad):");
test.withDuplicates();
System.out.println("\nAdding duplicates to a map (good):");
test.withoutDuplicates();
}
public void withDuplicates() {
NameBean bean1 = new NameBean("Alice");
NameBean bean2 = new NameBean("Alice");
java.util.Map<NameBean, String> map
= new java.util.HashMap<NameBean, String>();
map.put(bean1, "first");
map.put(bean2, "second");
System.out.println("Result of map.get(bean1):"+map.get(bean1));
System.out.println("Result of map.get(bean2):"+map.get(bean2));
System.out.println("Result of map.get(new NameBean(\"Alice\"): "
+ map.get(new NameBean("Alice")));
}
public void withoutDuplicates() {
ImprovedNameBean bean1 = new ImprovedNameBean("Alice");
ImprovedNameBean bean2 = new ImprovedNameBean("Alice");
java.util.Map<ImprovedNameBean, String> map
= new java.util.HashMap<ImprovedNameBean, String>();
map.put(bean1, "first");
map.put(bean2, "second");
System.out.println("Result of map.get(bean1):"+map.get(bean1));
System.out.println("Result of map.get(bean2):"+map.get(bean2));
System.out.println("Result of map.get(new ImprovedNameBean(\"Alice\"): "
+ map.get(new ImprovedNameBean("Alice")));
}
}