闲来无事,就实现一个简单的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原理)的更多相关文章

  1. Java中map集合系列原理剖析

    看了下JAVA里面有HashMap.Hashtable.HashSet三种hash集合的实现源码,这里总结下,理解错误的地方还望指正 HashMap和Hashtable的区别 HashSet和Hash ...

  2. Java:concurrent包下面的Map接口框架图(ConcurrentMap接口、ConcurrentHashMap实现类)

    Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...

  3. Java之Map接口(双列集合)

    Map集合概述 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射.Java提供了专门的集合类用来存放这种对象关系的对 ...

  4. Java核心数据结构(List、Map、Set)原理与使用技巧

    JDK提供了一组主要的数据结构实现,如List.Set等常用数据结构.这些数据都继承自java.util.Collection接口,并位于java.util包内. 一.List接口 最重要的三种Lis ...

  5. Java集合框架Map接口

    集合框架Map接口 Map接口: 键值对存储一组对象 key不能重复(唯一),value可以重复 常用具体实现类:HashMap.LinkedHashMap.TreeMap.Hashtable Has ...

  6. Java集合中的Map接口怎么使用?

    Map(双列集合框架) 1.Map接口及实现类概述 Map 接口提供三种collection 视图,允许以键集.值集或键-值映射关系集的形式查看某个映射的内容.映射顺序 定义为迭代器在映射的 coll ...

  7. 集合之Map接口

    Map接口概述 Map与Collection并列存在.用于存储具有映射关系的数据 : key-value Map 中的 key 和 value 都可以是任何引用类型的数据 Map 中的 key 用Se ...

  8. 函数式 js 接口实现原理,以及 lodash/fp 模块

    函数式 js 接口 之前在 youtube 上看到一个技术视频,讲“underscore.js的接口为什么不好用”,以及什么样的接口更好用.演讲者是 lodash.js 的作者,他提出了一种“全面函数 ...

  9. JAVA ,Map接口 ,迭代器Iterator

    1.    Map 接口概述 java.util.Map 接口描述了映射结构, Map 接口允许以键集.值集合或键 - 值映射关系集的形式查看某个映射的内容. Java 自带了各种 Map 类. 这些 ...

随机推荐

  1. spark als scala实现(二)

    Vi  t1.txt1,101,5.01,102,3.01,103,2.52,101,2.02,102,2.52,103,5.02,104,2.03,101,2.53,104,4.03,105,4.5 ...

  2. 使用cmd查看电脑连接过的wifi密码并将密码发送至指定邮箱(三)

    之前,我写了使用cmd查看电脑连接过的wifi密码(二)和使用cmd查看电脑连接过的wifi密码(一)但其中的功能不完善,在本次的更新中新增了更多的功能,其实2018/10/24 就更新完成了,一直拖 ...

  3. drools规则引擎与kie-wb和kie-server远程执行规则(7.18.0.Final)

    最近研究了一下规则引擎drools. 这篇博客带你搭建并运行一个可在线编辑,在线打包,远程执行的规则引擎(drools) 本篇博客同时参考https://blog.csdn.net/chinrui/a ...

  4. python day05

    数字类型 1.整型:整数 num = 1000000000000 type(num) --->int 2.浮点型:小数 num = 123.2341 type(num) --->float ...

  5. Ubuntu本地文件上传至HDFS文件系统出现的乱码问题及解决方案

    1.问题来源及原因 用shell命令上传到HDFS中之后出现中文乱码,在shell命令窗口查看如图: 在eclipse中的文件HDFS查看工具查看如图: 原因:上传至HDFS文件系统的文本文件(这里是 ...

  6. Ubuntu安装Navicat 12 for MySQL

    环境准备 要想运行Navicat,必须先安装Wine,这个可以使用下面的命令来安装Wine: ubuntu@ubuntu ~ $ sudo apt-get install wine-stable 安装 ...

  7. (五)jdk8学习心得之默认方法

    五.默认方法 1. 使用方法:写在接口中,就是为了接口可以做一些事情. 2. 目的:有很多实现类,有一个公共的抽象方法,其实这些实现类实现该抽象方法的内容是完全一致的,完全没有必要都重新实现一遍.并且 ...

  8. Laravel-任务调度

    简介Cron 是 UNIX.SOLARIS.LINUX 下的一个十分有用的工具,通过 Cron 脚本能使计划任务定期地在系统后台自动运行.这种计划任务在 UNIX.SOLARIS.LINUX下术语为 ...

  9. kettle变量(param命名参数2)

    接arg参数: 通过命令行进行变量赋值和引用 定义跟界面定义相同: 赋值(转换): 运行命令到kettle目录下 pan /file:path "/param:aa="bb&quo ...

  10. XML fragments parsed from previous mappers already contains value for xxxxx

    错误信息: Caused by: org.springframework.core.NestedIOException: Failed to parse mapping resource: 'file ...