java编程进阶小白也能手写HashMap代码

Java编程进阶:小白也能手写HashMap代码

前言

HashMap 是 Java 中常用的数据结构之一,它可以用于键值对存储和快速查找。虽然 Java 提供了 HashMap 的实现,但是手写 HashMap 算是 Java 编程基本功之一。本文将向大家介绍手写 HashMap 的完整攻略。

原理概述

Java 中 HashMap 是由数组和链表构成的,其主要原理是将 key 的 hashCode 计算出数组下标,如果该位置没有元素则直接插入,如果该位置已经有元素,则用链表的形式同步保存新的元素。

代码实现

下面我们来实现一个简单的 HashMap,代码清晰易懂。


public class MyHashMap<K, V> {

    private static final int INIT_CAPACITY = 16;

    private static final float LOAD_FACTOR = 0.75f;

    private int size;

    private int threshold;

    private Entry<K, V>[] table;

    public MyHashMap() {
        table = new Entry[INIT_CAPACITY];
        threshold = (int) (INIT_CAPACITY * LOAD_FACTOR);
    }

    static class Entry<K, V> {
        K key;
        V value;
        Entry<K, V> next;

        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }

    public void put(K key, V value) {
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K, V> e = table[i]; e != null; e = e.next) {
            if (e.key.equals(key)) {
                e.value = value;
                return;
            }
        }
        addEntry(key, value, hash, i);
    }

    public V get(K key) {
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K, V> e = table[i]; e != null; e = e.next) {
            if (e.key.equals(key)) {
                return e.value;
            }
        }
        return null;
    }

    private int indexFor(int h, int length) {
        return h & (length - 1);
    }

    private int hash(K key) {
        return key.hashCode();
    }

    private void addEntry(K key, V value, int hash, int bucketIndex) {
        Entry<K, V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<>(key, value);
        table[bucketIndex].next = e;
        size++;
        if (size >= threshold) {
            resize(table.length * 2);
        }
    }

    private void resize(int newCapacity) {
        Entry<K, V>[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity >= 1 << 30) {
            threshold = Integer.MAX_VALUE;
            return;
        }
        Entry<K, V>[] newTable = new Entry[newCapacity];
        transfer(newTable);
        table = newTable;
        threshold = (int) (newCapacity * LOAD_FACTOR);
    }

    @SuppressWarnings("unchecked")
    private void transfer(Entry<K, V>[] newTable) {
        Entry<K, V>[] src = table;
        int newCapacity = newTable.length;
        for (int j = 0; j < src.length; j++) {
            Entry<K, V> e = src[j];
            if (e != null) {
                src[j] = null;
                do {
                    Entry<K, V> next = e.next;
                    int i = indexFor(e.key.hashCode(), newCapacity);
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }
    }
}

示例说明

下面我们利用前面的 HashMap 实现,进行两个操作进行说明:

  1. 存放一个键为"name", 值为"张三"的元素
  2. 根据 key "name" 获取相应的值

public class Test {
    public static void main(String[] args) {
        MyHashMap<String, String> map = new MyHashMap<>();
        map.put("name", "张三");
        String name = map.get("name");
        System.out.println(name); // 输出"张三"
    }
}

总结

手动实现 HashMap 需要对 HashMap 的实现原理熟悉,以及对数组和链表处理的掌握,本文大概介绍了 HashMap 的实现原理,并提供了一个 Java 实现示例供大家导入使用或对其进行学习、修改等操作。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java编程进阶小白也能手写HashMap代码 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • 教你如何写springboot接口

    教你如何写Spring Boot接口攻略 1. 确定项目需求和数据库设计 在编写Spring Boot接口前,需要先明确项目需求和数据库设计,包括接口需要实现哪些功能,数据表的关系等。这样才能确保编写出的接口满足项目需求。同时,我们还需要确定使用的数据库类型和数据库连接方式。 2. 创建Spring Boot项目 接下来我们需要使用Spring Initia…

    Java 2023年5月19日
    00
  • 本地编译打包项目部署到服务器并且启动方式

    下面是本地编译打包项目部署到服务器并且启动方式的完整攻略: 准备工作 确定服务器的操作系统、IP地址、用户名和密码等信息。 确认服务器是否已经安装项目依赖的环境(例如Node.js、Java等)。 安装需要的打包工具(例如Maven、Gradle等),并且熟悉其中的一种。 步骤说明 以下是部署项目到服务器的步骤: 步骤一:本地编译打包项目 使用打包工具对项目…

    Java 2023年5月26日
    00
  • java文件读写操作实例详解

    下面是对“java文件读写操作实例详解”的完整攻略,包含以下几个部分: 1. 概述 文件读写操作是程序开发中经常用到的一项基础操作,Java提供了丰富的文件读写API,能够满足各种不同的需求。文件读写操作包括文件读取、文件写入、文件拷贝等。 2. 文件读取操作 Java提供了多种读取文件的方式,常用的方式包括IO流、NIO、FileReader等。下面以Fi…

    Java 2023年5月20日
    00
  • net操作access数据库示例分享

    下面是详细的“net操作access数据库示例分享”的攻略。 简介 在使用.NET框架进行开发时,经常需要操作数据库。使用.NET操作Access数据库可以使用两种方式:OleDb和Odbc。OleDb适用于Access、Excel和SQL Server等数据库,而Odbc适用于通用数据库。下文将以OleDb方式为例,分享操作Access数据库的示例。 前置…

    Java 2023年5月19日
    00
  • 详解Spring框架入门

    下面我将为您详细讲解“详解Spring框架入门”的完整攻略。 1. 什么是Spring框架 Spring框架是一个用于Java应用程序开发的开源框架。它最初由Rod Johnson在2002年创建,旨在提供一种允许Java程序员开发企业级应用程序的框架。Spring框架基于Java语言,使用IoC(Inversion of Control)和AOP(Aspe…

    Java 2023年5月20日
    00
  • Java中循环冗余校验(CRC32)的实现

    Java中循环冗余校验(CRC32)的实现 简介 循环冗余校验(CRC)是一种根据数据产生校验码的技术,它主要用于检测或者校验数据,以确定数据的完整性和准确性。在Java中,CRC32是循环冗余校验算法的一种常用实现。 实现步骤 1. 使用java.util.zip.CRC32类 Java提供了java.util.zip.CRC32类来实现CRC32算法。这…

    Java 2023年5月19日
    00
  • java hibernate使用注解来定义联合主键

    下面是Java Hibernate使用注解来定义联合主键的完整攻略。 什么是联合主键? 在关系型数据库中,主键是用来唯一标识一条记录的,而联合主键(Compound Primary Key)是由多个字段组合而成的,用来唯一标识一条记录。在Java Hibernate中,定义联合主键可以使用注解来实现。 使用注解定义联合主键 定义实体类 在Java代码中定义需…

    Java 2023年5月19日
    00
  • Spring Boot JPA如何把ORM统一起来

    使用Spring Boot + JPA进行开发可以避免繁琐的ORM操作,让开发更加简单和高效。接下来,我们将详细讲解如何把ORM统一起来,包括定义实体类、配置数据源、定义Repository接口、使用JPA进行CRUD操作等步骤。同时,我们也会给出两个具体的示例供参考。 1. 定义实体类 ORM操作的前提是要定义实体类,对应数据库的表。实体类应该使用Java…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部