estudo detalhado equals () e hashCode ()
- A classe Object é a classe pai de cada classe, e todos os objetos implementam os métodos definidos em Object.
equals()、hashCode()
Eles sãojava.lang.Object
os métodos em.
é igual a()
Equals () na classe Object
public boolean equals(Object obj) {
return (this == obj);
}
Use o sinal de igual para determinar se dois objetos são iguais e a representação do objeto na memória é a identificação (endereço de memória) e o estado (dados).
Sinal de igualdade ==
e equals()
problema de igualdade
- O sinal de igual compara se os endereços de memória de dois objetos são iguais.
- equals () compara se o conteúdo do objeto é igual.
Exemplo 1
String a = "123";
String b = "123";
System.out.println(a==b?"yes":"no");
- A maneira como a e b são criados pode ou não criar um objeto. Se a string atribuída não existir no conjunto de strings java, um
a="123"
objeto será criado no conjunto de strings e, em seguida, aeb apontarão para este endereço de memória, e então Quando criado desta forma, apenas um endereço é sempre atribuído.
O resultado de saída no exemplo 1 deve ser sim, porque a == b julga se os endereços dos objetos são iguais e os endereços de aeb são iguais neste momento por meio de uma análise abrangente.
Exemplo 2
String c = new String("123");
String d = new String( "123");
System.out.println(c==d?"yes":"no");
new String()
Pelo menos um objeto será criado e é possível criar dois.Um objeto de c será criado no heap, e se a string não existir no pool de String."123"
Este objeto será criado no pool String .
O resultado de saída no Exemplo 2 é Não, que está new String()
relacionado. Neste momento, use == para julgar quando os endereços dos dois objetos são diferentes, então o valor é não.
Reescreva equals () para classes como String
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
hashCode ()
O método hashCode () retorna um valor de código hash para o objeto.Este método é usado em tabelas hash.
-
Se eles
equal(Object)
forem iguais de acordo com o método, chamar os doishashCode()
métodos deve produzir o mesmo resultado interno. -
Quando o método equals é reescrito, geralmente é necessário reescrever o método hashCode para manter o contrato convencional do método hashCode, que afirma que objetos iguais devem ter códigos hash iguais.
A definição do método hashCode () na classe Object
public native int hashCode();
- A existência de hashCode é usada principalmente para a rapidez da pesquisa, como Hashtable, HashMap, etc. O hashCode é usado para determinar o endereço de armazenamento do objeto na estrutura de armazenamento de hash.
Substituir equals () e hashCode ()
public class User {
private int id;
private String name;
private String address;
public User(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
return id == user.id &&
Objects.equals(name, user.name) &&
Objects.equals(address, user.address);
}
@Override
public int hashCode() {
return Objects.hash(id, name, address);
}
// setget()省略
}
Se apenas o método equals () for substituído, num será nulo. O objeto apontado pelo usuário e o novo objeto em map.get () são dois objetos e seus endereços de armazenamento são diferentes.
@Test
public void test1(){
User user = new User(1,"张三","test1");
System.out.printf(String.valueOf(user.hashCode()));
HashMap<User,Integer> map = new HashMap<>(16);
map.put(user,23);
System.out.print("=======");
Integer num = map.get(new User(1, "张三", "test1"));
System.out.printf(String.valueOf(num));
}
HashMap e get ()
- método get (), se getNode () for Nulo, get () retornará nulo.
- getNode ()
- Hash é o hash da chave, e o parâmetro formal chave é a chave
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
// 成员变量table不为空,且table的长度大于0,并且经过hash函数计算的存储单元不为空
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
// 第一个节点的hash值等于hash 且第一个节点的key等于key
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
// 返回第一个节点
return first;
// 该存储单元链接了多个节点
if ((e = first.next) != null) {
// 节点以红黑树的方式连接
// 第一个节点的类型是树节点类型
if (first instanceof TreeNode)
// 调用红黑树中查找的方法
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
// 循环的方式在链表中查找
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
// 找不到返回null
return null;
}