【Java数据结构】自己实现一个HahMap(实现其put, toString, get方法)

本文深入探讨了自定义HashMap的实现原理,包括键值对存储、冲突处理、遍历及查找等核心操作,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HashMap

HashMap存储的是:键值对 (key, value)

HashMap的Key可以冲突,在冲突时,覆盖原有的Key对应的Value值。
下面是一个Key冲突的例子,运行效果如下:
在这里插入图片描述
目标位置相同时,节点形成链表。如下
在这里插入图片描述

代码(一共三个版本,最终版在最下面)

  • 版本一:put方法

MyHashMap.java

package cn.hanquan.file;

public class MyHashMap {
	Node[] table;// 位桶数组
	int size;// 存放键值对的个数

	public MyHashMap() {
		table = new Node[16];
	}

	public void put(Object key, Object value) {
		// 定义新节点对象
		Node newNode = new Node();
		newNode.hash = myHash(key.hashCode(), table.length);
		newNode.key = key;
		newNode.value = value;
		newNode.next = null;

		Node temp = table[newNode.hash];// 用来检查位置是否被占用
		Node last = null;// 临时存储上一个节点
		if (temp == null) {// 未占用
			table[newNode.hash] = newNode;
		} else {// 被占用

			while (temp != null) {
				if (temp.key.equals(key)) {// 重复
					System.out.println("key重复: key=" + key + ",value=" + value);
					temp.value = value;// 覆盖value, 而hash, key, next保持不变
					return;
				} else {// 不重复
					last = temp;// 小弟踩着大哥脚印
					temp = temp.next;// 大哥先走一步
				}
			}
			last.next = newNode;
		}

	}

	public static void main(String[] args) {
		MyHashMap h = new MyHashMap();
		System.out.println("长度:" + h.table.length);
		h.put(10, "aa");
		h.put(20, "bb");
		h.put(30, "cc");
		h.put(20, "ssss");
		System.out.println("执行完毕");
	}

	// 计算放入那个桶
	public int myHash(int v, int length) {
		System.out.println("hash=" + (v % length));
		return v % length;
	}
}

Node.java

package cn.hanquan.file;

public class Node {
	int hash;
	Object key;
	Object value;
	Node next;
}

  • 版本二:添加 toString 方法

Node.java

package cn.hanquan.file;

public class Node {
	int hash;
	Object key;
	Object value;
	Node next;
}

MyHashMap.java

package cn.hanquan.file;

/*
 * 实现put方法,增加一个元素
 * 实现toString方法,仿版查看map中的键值对信息
 */
public class MyHashMap {
	Node[] table;// 位桶数组
	int size;// 存放键值对的个数

	public MyHashMap() {
		table = new Node[16];
	}

	public void put(Object key, Object value) {
		// 定义新节点对象
		Node newNode = new Node();
		newNode.hash = myHash(key.hashCode(), table.length);
		// System.out.println("key=" + key + "hashCode=" + key.hashCode());
		newNode.key = key;
		newNode.value = value;
		newNode.next = null;

		Node temp = table[newNode.hash];// 用来检查位置是否被占用
		Node last = null;// 临时存储上一个节点
		if (temp == null) {// 未占用
			table[newNode.hash] = newNode;
		} else {// 被占用

			while (temp != null) {
				if (temp.key.equals(key)) {// 重复
					System.out.println("key重复: key=" + key + ",value=" + value);
					temp.value = value;// 覆盖value, 而hash, key, next保持不变
					return;
				} else {// 不重复
					last = temp;// 小弟踩着大哥脚印
					temp = temp.next;// 大哥先走一步
				}
			}
			last.next = newNode;
		}

	}

	public String toString() {
		StringBuilder sb = new StringBuilder("{");
		for (int i = 0; i < table.length; i++) {
			Node temp = table[i];

			while (temp != null) {// 遍历链表
				sb.append("[" + i + "]" + temp.key + "->" + temp.value + ",");// 不纠结最后多余的逗号,后面直接替换成}就行
				temp = temp.next;
			}
		}
		sb.setCharAt(sb.length() - 1, '}');
		return sb.toString();
	}

	public static void main(String[] args) {
		MyHashMap h = new MyHashMap();
		System.out.println("长度:" + h.table.length);
		h.put(10, "aa");
		System.out.println(h.toString());
		h.put(20, "bb");
		System.out.println(h.toString());
		h.put(30, "cc");
		System.out.println(h.toString());
		h.put(20, "dd");
		System.out.println(h.toString());
		h.put(53, "ee");
		System.out.println(h.toString());
		h.put(69, "ff");
		System.out.println(h.toString());
		h.put(85, "gg");
		System.out.println(h.toString());
	}

	// 计算放入那个桶
	public int myHash(int v, int length) {
		// System.out.println("hash=" + (v % length));
		return v % length;
	}
}

运行结果

长度:16
{[10]10->aa}
{[4]20->bb,[10]10->aa}
{[4]20->bb,[10]10->aa,[14]30->cc}
key重复: key=20,value=dd
{[4]20->dd,[10]10->aa,[14]30->cc}
{[4]20->dd,[5]53->ee,[10]10->aa,[14]30->cc}
{[4]20->dd,[5]53->ee,[5]69->ff,[10]10->aa,[14]30->cc}
{[4]20->dd,[5]53->ee,[5]69->ff,[5]85->gg,[10]10->aa,[14]30->cc}


  • 版本三:增加 get 方法

Node.java

package cn.hanquan.file;

public class Node {
	int hash;
	Object key;
	Object value;
	Node next;
}

MyHashMap.java

package cn.hanquan.file;

/*
 * 实现put方法,增加一个元素
 * 实现toString方法,仿版查看map中的键值对信息
 * 实现get方法,通过键对象查找相对应的值对象
 */
public class MyHashMap {
	Node[] table;// 位桶数组
	int size;// 存放键值对的个数

	public MyHashMap() {
		table = new Node[16];
	}

	public void put(Object key, Object value) {
		// 定义新节点对象
		Node newNode = new Node();
		newNode.hash = myHash(key.hashCode(), table.length);
		// System.out.println("key=" + key + "hashCode=" + key.hashCode());
		newNode.key = key;
		newNode.value = value;
		newNode.next = null;

		Node temp = table[newNode.hash];// 用来检查位置是否被占用
		Node last = null;// 临时存储上一个节点
		if (temp == null) {// 未占用
			table[newNode.hash] = newNode;
			size++;
		} else {// 被占用

			while (temp != null) {
				if (temp.key.equals(key)) {// 重复
					System.out.println("key重复: key=" + key + ",value=" + value);
					temp.value = value;// 覆盖value, 而hash, key, next保持不变
					return;
				} else {// 不重复
					last = temp;// 小弟踩着大哥脚印
					temp = temp.next;// 大哥先走一步
				}
			}
			last.next = newNode;
			size++;
		}

	}

	public String toString() {
		StringBuilder sb = new StringBuilder("{");
		for (int i = 0; i < table.length; i++) {
			Node temp = table[i];

			while (temp != null) {// 遍历链表
				sb.append("[" + i + "]" + temp.key + "->" + temp.value + ",");// 不纠结最后多余的逗号,后面直接替换成}就行
				temp = temp.next;
			}
		}
		sb.setCharAt(sb.length() - 1, '}');
		return sb.toString();
	}

	public Object get(Object key) {
		int hash = MyHashMap.myHash(key.hashCode(), table.length);
		Node t = table[hash];
		while (t != null) {
			if (key == t.key)
				return t.value;
			else
				t = t.next;
		}
		System.out.println("你要查找的key不存在!");
		return null;
	}

	public static void main(String[] args) {
		MyHashMap h = new MyHashMap();

		h.put(10, "aa");
		h.put(20, "bb");
		h.put(30, "cc");
		h.put(20, "dd");
		h.put(53, "ee");
		h.put(69, "ff");
		h.put(85, "gg");
		System.out.println(h.toString());

		System.out.println(h.get(30));
	}

	// 计算放入那个桶
	public static int myHash(int v, int length) {
		// System.out.println("hash=" + (v % length));
		return v % length;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值