为什么jdk1.8之前HashMap是由List+链表组成?

在这里插入图片描述
欢迎关注微信公众号:数据科学与艺术

在jdk1.8之前,Java中的HashMap实现是由数组+链表的方式组成的。这样的设计是为了解决冲突问题,即当两个不同的键值映射到数组的同一个位置时,需要通过链表将它们连接起来。

优点:

  1. 实现简单:使用链表的方式可以方便地处理冲突问题,实现相对简单。
  2. 空间利用率高:链表的插入和删除操作相对高效,可以更好地利用内存空间。

缺点:

  1. 查找效率低:由于链表只能顺序查找,当需要查找特定键值对时,需要遍历整个链表,效率较低。
  2. 遇到长链表时性能下降:如果链表过长,会导致插入和查找操作的性能下降,因为需要遍历整个链表。

链表是由一系列节点组成的数据结构,每个节点包含一个数据元素和一个指向下一个节点的指针。链表的特点是插入和删除操作比较高效,但是查找操作需要遍历整个链表。

代码实现

在JDK1.8之前,HashMap是由数组+链表的形式实现的。下面是一个简单的代码示例:

import java.util.LinkedList;

public class HashMapBeforeJDK1_8<K, V> {
    private LinkedList<Pair<K, V>>[] buckets;
    private int capacity;
    
    public HashMapBeforeJDK1_8(int capacity) {
        this.capacity = capacity;
        buckets = new LinkedList[capacity];
    }
    
    public void put(K key, V value) {
        int index = indexForKey(key);
        if (buckets[index] == null) {
            buckets[index] = new LinkedList<>();
        }
        
        LinkedList<Pair<K, V>> bucket = buckets[index];
        
        Pair<K, V> newPair = new Pair<>(key, value);
        for (Pair<K, V> pair : bucket) {
            if (pair.getKey().equals(key)) {
                pair.setValue(value);
                return;
            }
        }
        
        bucket.add(newPair);
    }
    
    public V get(K key) {
        int index = indexForKey(key);
        LinkedList<Pair<K, V>> bucket = buckets[index];
        
        if (bucket != null) {
            for (Pair<K, V> pair : bucket) {
                if (pair.getKey().equals(key)) {
                    return pair.getValue();
                }
            }
        }
        
        return null;
    }
    
    private int indexForKey(K key) {
        return Math.abs(key.hashCode()) % capacity;
    }
    
    private static class Pair<K, V> {
        private K key;
        private V value;
        
        public Pair(K key, V value) {
            this.key = key;
            this.value = value;
        }
        
        public K getKey() {
            return key;
        }
        
        public V getValue() {
            return value;
        }
        
        public void setValue(V value) {
            this.value = value;
        }
    }
}

在这个示例中,HashMapBeforeJDK1_8类使用一个数组来表示HashMap的桶,每个桶是一个LinkedList<Pair<K, V>>类型的链表。put()方法用于向HashMap中添加键值对,get()方法用于根据键获取对应的值。indexForKey()方法用于计算键的哈希值并映射到对应的桶。Pair<K, V>是一个简单的键值对类,用于存储键值对的数据。

分析

以一个简单的案例来说明,假设我们要存储学生的姓名和对应的分数。使用HashMap可以实现快速根据姓名查找分数的功能。当两个不同学生的姓名映射到同一个数组位置时,HashMap会使用链表将它们连接起来。

例如,我们有两个学生"张三"和"李四",他们的姓名都映射到数组的索引位置1。如果使用了链表结构,将两个学生的信息存储在同一个位置上,可以更好地利用空间。当我们需要查找"张三"的分数时,只需要遍历链表即可。

而如果使用数组结构,则需要使用额外的数据结构存储冲突的元素,例如使用List。在这种情况下,当两个学生的姓名映射到同一个数组位置时,需要将它们存储在同一个List中。如果我们要查找"张三"的分数,需要遍历整个List才能找到对应的分数。这样的设计会导致查找效率的降低。

因此,通过使用数组+链表的方式实现HashMap可以在一定程度上提高空间利用率和插入/删除操作的效率,但在查找操作上有一些性能上的牺牲。在jdk1.8之后,HashMap的实现方式进行了改进,引入了红黑树来替代链表,以优化查找操作的性能。

  • 20
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
HashMap在1.8版本之前的实现中,使用的是数组和链表相结合的方式实现的。具体地说,每个数组元素都是一个链表的头节点,每个链表中存储了一些键值对。哈希函数将键映射到数组的下标位置,然后根据链表的遍历方式,找到相应的键值对。 这种实现方式的主要优点在于,可以解决哈希冲突的问题。由于哈希函数无法将每个键都映射到唯一的数组下标位置,所以可能发生哈希冲突,即多个键映射到了同一个数组下标位置。如果只是简单地将键值对存放在数组中,就会出现覆盖的情况。而使用链表可以解决这个问题,同一个数组下标位置上的多个键值对会存储在同一个链表中,不会互相覆盖。 然而,链表的缺点也很明显:当链表中存储的数据过多时,遍历链表的时间会很长,这会导致HashMap的性能下降。因此,在1.8版本之后,HashMap引入了红黑树的数据结构,用于优化链表过长的情况,提高遍历的效率。 ListJava中一种常见的数据结构,表示一个元素的有序集合。在HashMap中,链表就是一种单向的List。它的作用是将多个键值对存储在同一个数组下标位置上,实现链表的遍历查找,并解决哈希冲突的问题。对于HashMap的使用者而言,可以将它看做一个键值对的集合,通过键来访问和更新值。例如: ``` HashMap<String,Integer> hashMap = new HashMap<>(); hashMap.put("one",1); hashMap.put("two",2); hashMap.put("three",3); Integer value = hashMap.get("two"); System.out.println(value); // output: 2 ``` 这段代码创建了一个HashMap对象,将三个键值对添加到里面。然后,通过get()方法获取"two"键对应的值,并将其输出到控制台上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贺公子之数据科学与艺术

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值