实现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 类. 这些 ...
随机推荐
- 教你一步永久激活WebStorm2018
工欲善其事必先利其器,我们在开发过程中,编辑器是我们提高开发效率及生产必备的工具,如何发现一个高效好用的编辑器是程序员必备的技能之一. 前端开发有众多编辑器 sublime.vscode.webstr ...
- 线上centos6出现软死锁 kernel:BUG: soft lockup
线上centos6出现软死锁 kernel:BUG: soft lockup 今天线上一台centos6机器用xshell一直连接不上,然后在xshell上显示 Message from syslog ...
- VMware小记
博主最近不知道为啥,有点手贱,折腾虚拟机. 然后某天,突然发现虚拟机连不上网,ping物理机,返回结果是不可达. 后来尝试各种手段,注意到VMware Network Adapter VMnet8和 ...
- Windows 组策略的生效规则
一般的继承与处理规则 若上层父OU的某个组策略项目被设定,但是其下层子OU未设定该项目,则下层子OU继承上层父OU的这个组策略项目设定值 若在下层子OU内的某个组策略项目被设定,则此设定值预设会覆盖由 ...
- 《重构》的读书笔记–方法列表
第5章 重构列表 5.1 重构的记录格式103 5.2 寻找引用点105 5.3 这些重构手法有多成熟106 第6章 重新组织函数 6.1 (P110)Extract Method(提炼函数) 6.2 ...
- C#编程风格
开始实习之后,才发现自己是多么地菜.还有好多东西还要去学习. 公司很好,还可以帮你买书.有一天随口问了一下上司D,代码规范上面有什么要求.然后D在Amazon上面找到了这本书<C#编程风格(Th ...
- vue keepalive 动态设置缓存
场景:A首页.B列表页.C详情页B---->C 缓存‘列表1’详情的数据A---->C 读取‘列表1’详情的数据B---->C (希望清除‘列表1’的缓存,变成缓存‘列表2’详情的数 ...
- 【C语言】位运算
编写一个函数getbits,从一个16位的单元中取出某几位(即该几位保留原值,其余位0).函数调用形式为getbits(value,n1,2).----简单题目遇到想不到的问题 c语言位运算经典问题: ...
- Appuim的安装步骤
1.下载Appium Desktop并安装 下载地址:https://github.com/appium/appium-desktop/releases 我下载的版本为:appium-desktop- ...
- Windows之常用命令
1. 重启/关机 shutdown命令 #关机 shutdown -s -t -f #重启 shutdown -r -t //30秒之后,重启 00是立即 #注销 shutdown -l -t #休眠 ...