HashMap详解

一、HashMap原理

HashMap是基于哈希表的实现,它是一种将键映射到值的数据结构。

HashMap可以通过key来访问value,因此它提供了非常快速的(近似常数时间)查询操作。

HashMap采用数组、链表、红黑树结合的方式实现,数组被分为一个一个的桶,每个桶里面存放一条链表或者红黑树,当链表长度超过8,并且数组长度大于64时,链表就会转化为红黑树,这样可以提高查询效率。

二、HashMap和Map区别简答

Map是所有映射类型的基类,HashMap是Map接口的一种实现。

因此,HashMap继承了Map接口的所有属性和行为。在Java中,Map和HashMap都是非常常见的用于存储键值对的容器。

Map是一个映射接口,它提供了每个键都可以对应一个值的存储机制。HashMap是通过继承AbstractMap来实现的,而且它是一种基于哈希表的Map实现。

三、HashMap方法

HashMap提供了以下方法:

1. put(K key, V value):将指定的值与此映射中的指定键相关联。

2. get(Object key):返回此映射中指定键所映射的值。

3. remove(Object key):从此映射中移除指定键的映射。

4. containsKey(Object key):如果此映射包含指定键的映射,则返回true。

5. containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回true。

6. keySet():返回此映射中包含的键的Set视图。

7. values():返回此映射中包含的值的Collection视图。

8. entrySet():返回此映射中包含的映射的Set视图。

四、HashMap的理解

HashMap是一个用于存储键值对的数据结构,它提供了五种不同的存储方式:数组、链表、红黑树、字段元素、桶容量因子。其中,数组、链表和红黑树的实现来自于Java集合框架的LinkedList和TreeMap类,字段元素和桶容量因子则是HashMap独有的特性。

作为HashMap使用者,我们不需要了解HashMap内部的实现原理,只需要了解其提供的方法即可。但是如果想要深入了解Java集合框架,建议可以学习一下HashMap的源码实现。

五、HashMap的get方法

get方法是HashMap中最常用的方法之一,它用于返回与指定键相关联的值。在HashMap中,get方法可以通过以下步骤来完成:

1. 将key的hashCode作为参数入参传递给hash方法。

public V get(Object key) {
    Node e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

2. hash方法会将hashCode的高位异或低位,来保证一个更好的hash值分布,得到对应的桶的索引。

final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

3. 根据桶的索引定位到对应的桶,遍历桶中的链表,如果key相同,则返回对应的value。

final Node getNode(int hash, Object key) {
    Node[] tab;
    Node first, e;
    int n;
    K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

六、HashMap用法

HashMap用法非常广泛,可以通过创建HashMap对象,调用其提供的put方法,向HashMap中添加键值对:

HashMap map = new HashMap();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);

也可以通过get方法,从HashMap中获取指定键对应的值:

Integer value = map.get("apple");

七、HashMap集合说法正确的是

HashMap是一种无序的集合,它不保证集合中元素的顺序。

另外,HashMap中可以存储null值和null键。

八、HashMap集

HashMap是一种key-value的数据结构。

它的内部是通过哈希表的方式来存储数据的。

HashMap中的key和value都可以为null。

当HashMap中出现hash冲突的时候,会采用链表的方式来存储。

九、HashMap扩容

HashMap在存储元素的时候,存在一个负载因子(load factor)的概念。

当元素的数量达到负载因子与容量的乘积时,HashMap就会自动扩容。默认的负载因子是0.75,即当HashMap的元素数量达到容量的75%时,就会进行扩容。

在扩容的时候,HashMap会将元素重新分配到新的数组中。这个过程需要对每个元素重新计算hash值,因此效率较低。

十、HashMap源码选取

在HashMap中,我们可以看一下Node类的定义:

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;

    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public final K getKey()        { return key; }
    public final V getValue()      { return value; }
    public final String toString() { return key + "=" + value; }

    public final int hashCode() {
        return Objects.hashCode(key) ^ Objects.hashCode(value);
    }

    public final V setValue(V newValue) {
        V oldValue = value;
        value = newValue;
        return oldValue;
    }

    public final boolean equals(Object o) {
        if (o == this)
            return true;
        if (o instanceof Map.Entry) {
            Map.Entry e = (Map.Entry)o;
            if (Objects.equals(key, e.getKey()) &&
                Objects.equals(value, e.getValue()))
                return true;
        }
        return false;
    }
}

Node类用于存储键值对,也就是哈希表中的元素。它包含了hashCode、key、value、next四个字段,其中hashCode是计算得到的键的哈希值,key和value分别对应键和值,next是指向下一个元素的指针。

原创文章,作者:DDXW,如若转载,请注明出处:https://www.506064.com/n/136711.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
DDXWDDXW
上一篇 2024-10-04 00:16
下一篇 2024-10-04 00:16

相关推荐

  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25
  • MPU6050工作原理详解

    一、什么是MPU6050 MPU6050是一种六轴惯性传感器,能够同时测量加速度和角速度。它由三个传感器组成:一个三轴加速度计和一个三轴陀螺仪。这个组合提供了非常精细的姿态解算,其…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25

发表回复

登录后才能评论