使用HashMap的注意事项

  Java   11分钟   844浏览   0评论

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);
        }
    }
}

总结

  1. HashMap的数据结构为数组+链表+红黑树(JDK8以后)键值均可为null,键唯一,值可重复
  2. 使用HashMap必须同时重写hashCode方法和equals方法
如果你觉得文章对你有帮助,那就请作者喝杯咖啡吧☕
微信
支付宝
  0 条评论