实现Map接口(hash原理)
闲来无事,就实现一个简单的map来练练手吧!
HashMap的底层实现主要是基于数组和链表来实现的,HashMap中通过key的hashCode来计算hash值的,由这个hash值计算在数组中的位置,将新插入的元素放到数组的这个位置,如果新插入的元素的hash值跟这个位置上已有元素的hash值相同,就会出现hash冲突,这时候,就在该位置通过链表来插入新的元素。

如图,紫色部分是hash数组,绿色部分是链表,是为了解决冲突而产生的。
在实现Map接口时还需要实现Entry接口,以便能取出Map中元素。
package chapter3.question5;
import java.util.Map;
public class SimpleEntry implements Map.Entry, Comparable {
private Object key;
private Object value;
public SimpleEntry(Object key, Object value) {
this.key = key;
this.value = value;
}
@Override
public int compareTo(Object o) {
SimpleEntry simpleEntry = (SimpleEntry) o;
return ((Comparable) key).compareTo(simpleEntry.key);
}
@Override
public Object getKey() {
return key;
}
@Override
public Object getValue() {
return value;
}
@Override
public Object setValue(Object value) {
Object result = this.value;
this.value = value;
return result;
}
@Override
public String toString() {
return key + "=" + value;
}
}
接下来就是Map的简单是实现啦。
package chapter3.question5;
import java.util.*;
public class SimpleMap implements Map {
private final static int SLOT = ;
private LinkedList[] bucket = new LinkedList[SLOT];
private int size = ;
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == ;
}
@Override
public boolean containsKey(Object key) {
int index = key.hashCode() % SLOT;
if (index < ) index = -index;
if (bucket[index] == null) return false;
LinkedList linkedList = bucket[index];
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
SimpleEntry entry = (SimpleEntry) iterator.next();
if (entry.getKey().equals(key)) {
return true;
}
}
return false;
}
@Override
public boolean containsValue(Object value) {
for (int i = ; i < SLOT; i++) {
if (bucket[i] != null) {
LinkedList linkedList = bucket[i];
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
SimpleEntry entry = (SimpleEntry) iterator.next();
if (entry.getValue().equals(value)) {
return true;
}
}
}
}
return false;
}
@Override
public Object get(Object key) {
int index = key.hashCode() % SLOT;
if (index < ) index = -index;
if (bucket[index] == null) return null;
LinkedList linkedList = bucket[index];
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
SimpleEntry entry = (SimpleEntry) iterator.next();
if (entry.getKey().equals(key)) {
return entry.getValue();
}
}
return null;
}
/**
* @param key
* @param value
* @return 此前与key关联的值
*/
@Override
public Object put(Object key, Object value) {
int index = key.hashCode() % SLOT;
if (index < ) index = -index;
SimpleEntry entry = new SimpleEntry(key, value);
Object prev = null;
if (bucket[index] == null) bucket[index] = new LinkedList();
LinkedList list = bucket[index];
boolean found = false;
ListIterator iterator = list.listIterator();
while (iterator.hasNext()) {
SimpleEntry simpleEntry = (SimpleEntry) iterator.next();
if (simpleEntry.equals(entry)) {//一对一
found = true;
prev = simpleEntry.getValue();
iterator.set(entry);
break;
}
}
if (!found) {
size++;
bucket[index].add(entry);
}
return prev;
}
@Override
public Object remove(Object key) {
SimpleEntry entry = null;
int index = key.hashCode() % SLOT;
if (index < ) index = -index;
if (bucket[index] == null) return null;
LinkedList linkedList = bucket[index];
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
SimpleEntry simpleEntry = (SimpleEntry) iterator.next();
if (simpleEntry.getKey().equals(key)) {
entry = simpleEntry;
iterator.remove();
size--;
break;
}
}
return entry;
}
@Override
public void putAll(Map m) {
Set set = m.entrySet();
for (Object object : set) {
Map.Entry oo = (Map.Entry) object;
put(oo.getKey(), oo.getValue());
}
}
@Override
public void clear() {
for (Object key : keySet()) {
remove(key);
}
size = ;
}
@Override
public Set keySet() {
Set set = new HashSet();
for (int i = ; i < SLOT; i++) {
if (bucket[i] != null) {
Iterator iterator = bucket[i].iterator();
while (iterator.hasNext()) {
set.add(((SimpleEntry) iterator.next()).getKey());
}
}
}
return set;
}
@Override
public Collection values() {
List list = new ArrayList();
for (int i = ; i < SLOT; i++) {
if (bucket[i] != null) {
Iterator iterator = bucket[i].iterator();
while (iterator.hasNext()) {
list.add(((SimpleEntry) iterator.next()).getValue());
}
}
}
return list;
}
@Override
public Set<Entry> entrySet() {
Set set = new HashSet();
for (int i = ; i < SLOT; i++) {
if (bucket[i] != null) {
Iterator iterator = bucket[i].iterator();
while (iterator.hasNext()) {
set.add(((SimpleEntry) iterator.next()));
}
}
}
return set;
}
@Override
public int hashCode() {
int j = ;
for (int i = ; i < SLOT; i++) {
if (bucket[i] != null) {
Iterator iterator = bucket[i].iterator();
j += ((SimpleEntry) iterator.next()).getKey().hashCode();
}
}
return j;
}
/**
* 为了测试显示map内容
*
* @return
*/
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (int i = ; i < SLOT; i++) {
if (bucket[i] != null) {
Iterator iterator = bucket[i].iterator();
while (iterator.hasNext()) {
SimpleEntry entry = (SimpleEntry) iterator.next();
stringBuilder.append(entry.getKey() + "," + entry.getValue() + "\n");
}
}
}
return stringBuilder.toString();
}
}
实现Map接口(hash原理)的更多相关文章
- Java中map集合系列原理剖析
看了下JAVA里面有HashMap.Hashtable.HashSet三种hash集合的实现源码,这里总结下,理解错误的地方还望指正 HashMap和Hashtable的区别 HashSet和Hash ...
- Java:concurrent包下面的Map接口框架图(ConcurrentMap接口、ConcurrentHashMap实现类)
Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...
- Java之Map接口(双列集合)
Map集合概述 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射.Java提供了专门的集合类用来存放这种对象关系的对 ...
- Java核心数据结构(List、Map、Set)原理与使用技巧
JDK提供了一组主要的数据结构实现,如List.Set等常用数据结构.这些数据都继承自java.util.Collection接口,并位于java.util包内. 一.List接口 最重要的三种Lis ...
- Java集合框架Map接口
集合框架Map接口 Map接口: 键值对存储一组对象 key不能重复(唯一),value可以重复 常用具体实现类:HashMap.LinkedHashMap.TreeMap.Hashtable Has ...
- Java集合中的Map接口怎么使用?
Map(双列集合框架) 1.Map接口及实现类概述 Map 接口提供三种collection 视图,允许以键集.值集或键-值映射关系集的形式查看某个映射的内容.映射顺序 定义为迭代器在映射的 coll ...
- 集合之Map接口
Map接口概述 Map与Collection并列存在.用于存储具有映射关系的数据 : key-value Map 中的 key 和 value 都可以是任何引用类型的数据 Map 中的 key 用Se ...
- 函数式 js 接口实现原理,以及 lodash/fp 模块
函数式 js 接口 之前在 youtube 上看到一个技术视频,讲“underscore.js的接口为什么不好用”,以及什么样的接口更好用.演讲者是 lodash.js 的作者,他提出了一种“全面函数 ...
- JAVA ,Map接口 ,迭代器Iterator
1. Map 接口概述 java.util.Map 接口描述了映射结构, Map 接口允许以键集.值集合或键 - 值映射关系集的形式查看某个映射的内容. Java 自带了各种 Map 类. 这些 ...
随机推荐
- DVWA 黑客攻防演练(十一) 存储型 XSS 攻击 Stored Cross Site Scripting
上一篇文章会介绍了反射型 XSS 攻击.本文主要是通过 dvwa 介绍存储型 XSS 攻击.存储型 XSS 攻击影响范围极大.比如是微博.贴吧之类的,若有注入漏洞,再假如攻击者能用上一篇文章类似的代码 ...
- Scrapy框架-Spider
目录 1. Spider 2.Scrapy源代码 2.1. Scrapy主要属性和方法 3.parse()方法的工作机制 1. Spider Spider类定义了如何爬取某个(或某些)网站.包括了爬取 ...
- mac上修改host
host文件下载地址: https://github.com/highsea/Hosts/blob/master/hosts https://github.com/racaljk/hosts 备份ma ...
- cordova 自定义 plugin
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_30879415/article/details/81265455准备工作安装cordovanp ...
- Pandas 数据清洗常用篇
一.缺失值 sklearn中的preprocessing下有imputer,可进官方文档参考.这里主讲pandas. 拿到数据,一般先检查是否有缺失值,用isnul()或notnull(). 再决定d ...
- 这可能是最简单的Page Object库
做过web自动化测试的同学,对Page object设计模式应该不陌生. Page object库应该根据以下目标开发: Page object应该易于使用 清晰的结构 PageObjects 对于页 ...
- 在Winform系统界面中对进展阶段的动态展示和处理
在我们做客户关系管理系统的Winform界面的时候,需要对进展阶段这个属性进行一个方便的动态切换和标记处理,如我们根据不同的进展阶段显示不同的相关信息,也可以随时保存当前的阶段信息.其实也是一个比较常 ...
- Alpha阶段事后分析
设想和目标 我们在Alpha阶段对网站的定位布局一直在摸索,网站所有功能和网站所能解决的需求痛点并不是在前几次会议就定死了的.Alpha阶段整个过程中我们团队靠着频繁的scrum会议和微信群交(shu ...
- random使用方法
random.random() 没有参数,选择0到1之间的随机浮点数 random.uniform(a, b) 生成指定范围内的随机浮点数如果a.b哪个大那个小都没关系,生成的都是在小的与大的之间的随 ...
- c++ 重点随记
1.在公有继承中:(1).派生类对象储存了基类的私有成员 (2).派生类对象可以使用基类的方法 (3).基类引用可以引用派生类对象,派生类引用不可以引用基类对象 2.基类引用引用派生类对象时:若基类引 ...