Javamapget详解

发布时间:2023-05-21

一、基础概念

Javamapget 是 Java 中常用的 Map 的获取元素的方法,基于键值对的 Map 在 Java 开发中被广泛应用,在很多场景下需要通过键值对找到对应的元素,这时我们就需要使用 Mapget 方法。 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

上述代码创建了一个键值对为 StringIntegerHashMap,并向其中添加了 applebananaorange 三个键和对应的值。接着通过 map.get 方法获取了键为 banana 的值,并输出结果。

二、使用注意事项

  1. 键值类型需重写 hashCodeequals 方法 在使用 Map 的时候需要确保存储的键值类型已经正确重写了 hashCodeequals 两个方法。在 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 类,并在其中重写了 hashCodeequals 方法。接下来创建一个存储 StudentInteger 类型的 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

上述代码向一个存储 StringInteger 类型的 HashMap 中添加了多个元素,包括一个重复的键值和一个键为 null 的元素。由于 HashMap 只能存储唯一的键值,因此最后输出的结果为 4null

三、常见问题解决

  1. 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 是线程安全的,因此即使在多线程条件下,也可以保证程序的正确性。