Java难点 | HashMap和哈希表数据结构

简介: 本文详细的对HashMap和哈希表数据结构进行了详细的介绍,通过代码实战,深入浅出的讲解,让你对HashMap和哈希表数据结构更加掌握。

HashMap和哈希表数据结构

**HashMap集合key部分允许null吗?
允许
但是要注意:HashMap集合的key null值只能有一个。有可能面试的时候遇到这样的问题。**

**HashMap集合:
1、HashMap集合底层是哈希表/散列表的数据结构。
2、哈希表是一个怎样的数据结构呢?
哈希表是一个数组和单向链表的结合体。
数组:在查询方面效率很高,随机增删方面效率很低。
单向链表:在随机增删方面效率较高,在查询方面效率很低。
哈希表将以上的两种数据结构融合在一起,充分发挥它们各自的优点。**

**3、最主要掌握的是:
map.put(k,v)
map.get(k)
以上这两个方法的实现原理,是必须掌握的。**

**4、HashMap集合的key部分特点:无序,不可重复。
为什么无序?因为不一定挂到哪个单向链表上。
不可重复是怎么保证的?equals方法来保证HashMap集合的key不可重复。如果key重复了,value会覆盖。
放在HashMap集合key部分的元素其实就是放到HashSet集合中了。所以HashSet集合中的元素也需要同时重写hashCode()+equals()**

**5、哈希表HashMap使用不当时无法发挥性能!
假设将所有的hashCode()方法返回值固定为某个值,那么会导致底层哈希表变成了纯单向链表。这种情况我们成为:散列分布不均匀。什么是散列分布均匀?
假设有100个元素,10个单向链表,那么每个单向链表上有10个节点,这是最好的。是散列分布均匀的。
假设将所有的hashCode()方法返回值都设定为不一样的值,可以吗,有什么问题?
不行,因为这样的话导致底层哈希表就成为一维数组了,没有链表的概念了。也是散列分布不均匀。
散列分布均匀需要你重写hashCode()方法时有一定的技巧。**
在这里插入图片描述

同时重写hashCode和equals方法

**1、向Map集合中存,以及从Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法! equals方法有可能调用,也有可能不调用。
==拿put(k,v)举例,什么时候equals不会调用?==
k.hashCode()方法返回哈希值
哈希值经过哈希算法转换成数组下标。
数组下标位置上如果是null,eauals不需要执行。
==拿get(k)举例,什么时候equals不会调用?==
k.hashCode()方法返回哈希值,
哈希值经过哈希算法转换成数组下标。
数组下标位置上如果是null,equals不需要执行。**

**2、注意:如果一个类的equals方法重写了,那么hashCode()方法必须重写。并且equals方法返回如果是true,hashCode()方法返回的值必须一样。
equals方法返回true表示两个对象相同,在同一个单向链表上比较。那么对于同一个单向链表上的节点来说,他们的哈希值都是相同的。所以hashCode()方法的返回值也应该相同。**

3、hashCode()方法和equals()方法不用研究了,直接使用IDEA工具生成,但是这两个方法需要同时生成。

**4、终极结论:
放在HashMap集合key部分的,以及放在HashSet集合中的元素,需要同时重写hashCode方法和equals方法。**

**5、对于哈希表数据结构来说:
如果o1和o2的hash值相同,一定是放到同一个单向链表上。
当然如果o1和o2的hash值不同,但由于哈希算法执行结束之后转换的数组下标可能相同,此时会发生“哈希碰撞”。**

HashMap存储自定义类型键值

**HashMap存储自定义类型键值
Map集合保证key是唯一的:
作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一**

举例

Person类

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        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);
    }

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

主方法

public class 主方法 {
    public static void main(String[] args) {
        show01();
        show02();
    }

    /*
        HashMap存储自定义类型键值
        key:String类型
            String类重写了hashCode和equals方法,可以保证key唯一
        value:Person类型
            value可以重复(同名同年龄的人视为同一个)
     */
    private static void show01() {
        //创建HashMap集合
        HashMap<String,Person> map =new HashMap<>();
        //往集合添加元素  key有重复会把新的value替换原来的value
        map.put("北京",new Person("张三",18));
        map.put("上海",new Person("李四",19));
        map.put("广州",new Person("王五",20));
        map.put("北京",new Person("赵六",18));
         //使用keySet加增强for遍历map集合
        Set<String> set = map.keySet();
        for (String s : set) {
            Person s1 = map.get(s);
            System.out.println(s+"-->"+s1);
        }
    }

    /*
        HashMap存储自定义类型键值
        key:Person类型
            Person类必须重写hashCode和equals方法,以保证key唯一
        value:String类型
            可以重复
     */
    private static void show02() {
        //创建HashMap集合
        HashMap<Person,String> map =new HashMap<>();
        //往集合添加元素
        map.put(new Person("女王",18),"英国");
        map.put(new Person("秦始皇",18),"秦国");
        map.put(new Person("普京",30),"俄罗斯");
        map.put(new Person("女王",18),"b国");
        //使用entryset和增强for遍历map集合
        Set<Map.Entry<Person, String>> entries = map.entrySet();
        for (Map.Entry<Person, String> entry : entries) {
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"-->"+value);
        }

    }
}
相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
69 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
26天前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
42 1
|
28天前
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
81 2
|
28天前
|
存储 Java 开发者
Java Map实战:用HashMap和TreeMap轻松解决复杂数据结构问题!
【10月更文挑战第17天】本文深入探讨了Java中HashMap和TreeMap两种Map类型的特性和应用场景。HashMap基于哈希表实现,支持高效的数据操作且允许键值为null;TreeMap基于红黑树实现,支持自然排序或自定义排序,确保元素有序。文章通过具体示例展示了两者的实战应用,帮助开发者根据实际需求选择合适的数据结构,提高开发效率。
60 2
|
1月前
|
算法 Java 数据库
数据结构与算法学习十五:哈希表
这篇文章详细介绍了哈希表的概念、应用实例、实现思路,并提供了使用Java实现的哈希表代码。
53 0
数据结构与算法学习十五:哈希表
|
11天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
33 6
|
17天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
25天前
|
存储 算法 Java
Java 中常用的数据结构
【10月更文挑战第20天】这些数据结构在 Java 编程中都有着广泛的应用,掌握它们的特点和用法对于提高编程能力和解决实际问题非常重要。
24 6
|
26天前
|
存储 Java 开发者
Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效
【10月更文挑战第19天】在软件开发中,随着项目复杂度的增加,数据结构的组织和管理变得至关重要。Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,帮助开发者告别混乱,提升代码质量。
26 1
|
1月前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
31 6