热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HashMap原理及简单实现

publicclassMyHashMap<K,V>{privateclassEntry<K,V>{inthash;Kkey;V
public class MyHashMap {
	private class Entry {
		int hash;
		K key;
		V value;
		Entry next;

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

	private static final int DEFAULT_CAPACITY = 1 <<2;

	private Entry[] table;

	private int capacity;

	private int size;

	private final float loadFactor = 0.75f;

	public MyHashMap() {
		this(DEFAULT_CAPACITY);
	}

	@SuppressWarnings("unchecked")
	public MyHashMap(int capacity) {
		if (capacity <0) {
			throw new IllegalArgumentException();
		} else {
			table = new Entry[capacity];
			size = 0;
			this.capacity = capacity;
		}
	}

	public int size() {
		return size;
	}

	public boolean isEmpty() {
		return size == 0 ? true : false;
	}

	public V put(K key, V value) {
		if (key == null) {
			throw new RuntimeException("key不可以为空!");
		}
		if (size >= capacity * loadFactor) {
			// 开始rehash
			resize(2 * table.length);
			int hash = (null != key) ? hash(key) : 0;
			int index = indexFor(hash, table.length);// 注意此时的table已经扩容了
		}
		V newValue = putEntry(key, value);
		return newValue;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void resize(int newCapacity) {
		System.out.println("我们要扩容了!!当前的size是:" + size);
		// 让数组长度乘以两倍
		Entry[] newTable = new Entry[newCapacity];
		transfer(newTable, true);
		table = newTable;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void transfer(Entry[] newTable, boolean rehash) {
		int newCapacity = newTable.length;
		for (Entry e : table) {
			while (e != null) {
				if (rehash) {
					// 要重新hash
					e.hash = null == e.key ? 0 : hash(e.key);
				}
				int index = indexFor(e.hash, newCapacity);
				// 开始把e放进新的数组中
				// 注意,每次插入新的值都必须要插在散列链表的头部
				e.next = newTable[index];
				newTable[index] = e;
				e = e.next;
			}
		}
	}

	private V putEntry(K key, V value) {
		if (key == null) {
			throw new RuntimeException("key不可以为空!");
		}
		int hash = hash(key);
		int i = indexFor(hash, table.length);
		Entry newEn = new Entry(hash, key, value, null);
		for (Entry e = table[i]; e != null; e = e.next) {
			Object k;
			if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
				// 代表当前的e和要添加的key冲突了,那么就覆盖
				V oldValue = e.value;
				e.value = value;// 当前的e的value要替换为新的value
				return oldValue;
			}
		}
		// 如果上面没有找到的话,就要往链表添加元素了
		size++;
		addEntry(newEn, i);
		return value;
	}

	private void addEntry(Entry entry, int index) {
		Entry e = table[index];
		table[index] = entry;
		entry.next = e;
	}

	public V get(K key) {
		if (key == null) {
			throw new RuntimeException("key不可以为空!");
		}
		Entry entry = getEntry(key);
		return null == entry ? null : entry.value;
	}

	private Entry getEntry(K key) {
		if (size == 0) {
			return null;
		}
		int hash = (key == null) ? 0 : hash(key);
		int i = indexFor(hash, table.length);
		for (Entry e = table[i]; e != null; e = e.next) {
			Object k;
			if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
				return e;
			}
		}
		return null;
	}

	public V remove(K key) {
		Entry e = removeEntryForKey(key);
		return (e == null ? null : e.value);
	}

	private Entry removeEntryForKey(K key) {
		if (size == 0) {
			return null;
		}
		int hash = (key == null) ? 0 : hash(key);
		int i = indexFor(hash, table.length);
		Entry cur = table[i];
		Entry e = cur;
		while (e != null) {
			if (e.hash == hash && (e.key == key || key.equals(e.key))) {
				size--;
				// 如果删除的是prev的话
				if (cur == e) {
					table[i] = e.next;
				} else {
					// 就让cur的next等于e的next
					cur.next = e.next;
				}
				return e;
			}
			cur = e;
			e = e.next;
		}
		return null;
	}

	private int indexFor(int hash, int length) {
		return hash & (length - 1);// 哈希值和长度减一做与运算
	}

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

	public static void main(String[] args) {
		MyHashMap map = new MyHashMap<>();
	}
}

  


推荐阅读
  • 缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的。LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉。先说说List:每 ... [详细]
  • HashTable与ConcurrentHashMap均可实现HashMap的功能,对外提供了键值对存储的数据结构。但是在内部结构及实现上有何区别,性能上的差异到底在哪里又是如何导致的 ... [详细]
  • 将学生对象和学生的归属地通过键与值存储到map集合中。importjava.util.HashMap;importjava.util.Iterator;importjava.uti ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 我有3个来自RESEARCHS的映射值,指定要使用参考数据集填充的行中的范围。该研究 ... [详细]
  • 本篇文章给大家分享的是有关Java中怎么对HashMap按键值排序,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
author-avatar
兰勇2502919543
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有