HashMap
先看一个实例
package map;
import java.util.HashMap;
/**
* @author: 邹祥发
* @date: 2021/12/28 09:00
*/
public class HashMapDemo01 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("张三", "北京");
map.put("李四", "上海");
map.put("王五", "深圳");
map.put("张三", "北京");
System.out.println(map);
}
}
不出所料,HashMap的键是唯一的。
再看一个实例
package map;
import java.util.HashMap;
/**
* @author: 邹祥发
* @date: 2021/12/28 09:12
*/
public class HashMapDemo02 {
public static void main(String[] args) {
HashMap<Person, String> map = new HashMap<>();
map.put(new Person("张三", 18), "北京");
map.put(new Person("李四", 19), "上海");
map.put(new Person("张三", 18), "北京");
System.out.println(map);
}
static class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}
运行结果一出来,正在看文章的靓仔擦了擦自己的眼睛,试图告诉自己:这只是一个梦。
确认自己没看错之后,又想起了自己背过的Java面试八股文。
“HashMap的数据结构是数组+链表,JDK1.8后引入了红黑树,是线程不安全的,键唯一且可以为null.......”
问题出在Person类。
HashMap如何保证键的唯一性?
1.首先比较两个键的hashCode值
2.如果hashCode如同,则通过equals方法来判定是否“真的”相同
String中hashCode和equals方法源码
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
hash = h = isLatin1() ? StringLatin1.hashCode(value)
: StringUTF16.hashCode(value);
}
return h;
}
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
所以,我们在自定义的类中使用HashMap时必须重写hashCode方法和equals方法。
package map;
import java.util.HashMap;
import java.util.Objects;
/**
* @author: 邹祥发
* @date: 2021/12/28 09:12
*/
public class HashMapDemo02 {
public static void main(String[] args) {
HashMap<Person, String> map = new HashMap<>();
map.put(new Person("张三", 18), "北京");
map.put(new Person("李四", 19), "上海");
map.put(new Person("张三", 18), "北京");
System.out.println(map);
}
static class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
}
总结
- HashMap的数据结构为数组+链表+红黑树(JDK8以后),键值均可为null,键唯一,值可重复。
- 使用HashMap必须同时重写hashCode方法和equals方法。

评论区 0