一、基础概念
Javamapget
是 Java 中常用的 Map
的获取元素的方法,基于键值对的 Map
在 Java 开发中被广泛应用,在很多场景下需要通过键值对找到对应的元素,这时我们就需要使用 Map
的 get
方法。
get
方法接收一个键值作为参数,返回其对应的值。若 Map
中不存在该键值,则返回 null
。
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
Integer value = map.get("banana");
System.out.println(value);//输出2
上述代码创建了一个键值对为 String
和 Integer
的 HashMap
,并向其中添加了 apple
、banana
、orange
三个键和对应的值。接着通过 map.get
方法获取了键为 banana
的值,并输出结果。
二、使用注意事项
- 键值类型需重写
hashCode
和equals
方法 在使用Map
的时候需要确保存储的键值类型已经正确重写了hashCode
和equals
两个方法。在Map
内部,会根据键值对的hashCode
来定位元素,当hashCode
相同时,系统会调用equals
方法进一步判断是否相等,因此,当我们自定义类型作为键值时,需要确保这两个方法的正确实现。
public class Student {
private String name;
private int age;
//省略getter、setter方法以及其他成员变量和方法
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Student student = (Student) obj;
return age == student.age && Objects.equals(name, student.name);
}
}
Map<Student, Integer> map = new HashMap<>();
map.put(new Student("Tom", 18), 1);
map.put(new Student("Mary", 20), 2);
map.put(new Student("Lucy", 18), 3);
Integer value = map.get(new Student("Tom", 18));
System.out.println(value);//输出1
上述代码中定义了一个 Student
类,并在其中重写了 hashCode
和 equals
方法。接下来创建一个存储 Student
和 Integer
类型的 HashMap
,并向其中添加了三个元素。接着通过 map.get
方法获取键值为 new Student("Tom", 18)
的对应的值,并输出结果。
2. 必须保证键值唯一且不为 null
Map
中的键值对应关系是一一对应的,每个键只能对应一个值。如果添加了重复的键,则后面的值会覆盖前面的值。如果键为 null
,可能会导致 NullPointerException
异常。
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("orange", 2);
map.put("banana", 3);
map.put("banana", 4);
System.out.println(map.get("banana"));//输出4
System.out.println(map.get(null));//输出null
上述代码向一个存储 String
和 Integer
类型的 HashMap
中添加了多个元素,包括一个重复的键值和一个键为 null
的元素。由于 HashMap
只能存储唯一的键值,因此最后输出的结果为 4
和 null
。
三、常见问题解决
Map
中的元素顺序不可预知 Java 中的Map
并不保证元素的存储顺序。因此,在使用Map
的时候,不能依赖于元素的顺序。如果需要按照键值顺序访问元素,可以使用TreeMap
类型。
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
上述代码通过一个 for
循环遍历 HashMap
中的所有元素,并输出其键值。
2. 在多线程环境下调用 Map
的方法可能引起线程安全问题
HashMap
是非线程安全的,也就是说,在多个线程同时调用 HashMap
的方法会导致竞争条件的出现,从而引发数据异常或者程序错误。在多线程环境下,通常使用 ConcurrentHashMap
类型,或者将 HashMap
转换为线程安全的类型。
Map<String, Integer> map = new ConcurrentHashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
Integer value = map.get("apple");
if (value == null) {
map.put("apple", 1);
} else {
map.put("apple", value + 1);
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
Integer value = map.get("apple");
if (value == null) {
map.put("apple", 1);
} else {
map.put("apple", value + 1);
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(map.get("apple"));
上述代码中创建了一个 ConcurrentHashMap
,并向其中添加了多个元素。为了演示 HashMap
引发的线程安全问题,我们对 HashMap
进行了多线程测试。由于 ConcurrentHashMap
是线程安全的,因此即使在多线程条件下,也可以保证程序的正确性。