实现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 类. 这些 ...
随机推荐
- 无限极分类(adjacency list)的三种方式(迭代、递归、引用)
一般的分类树状结构有两种方式: 一种是adjacency list,也就是是id,parent id这中形式. 另一种是nested set,即左右值的形式. 左右值形式查询起来比较高效,无需递归等, ...
- 盖洛普Q12在团队中的应用
周五给大家做了个盖洛普Q12的分享. 分享前做了调查问卷.除了盖洛普Q12的12个问题: 1.我知道公司对我的工作要求吗? 2.我有做好我的工作所需要的材料和设备吗? 3.在工作中,我每天都有机会 ...
- crontab的笔试题随想
最近看到一道题目,具体如下: 下列哪个是创建一个每周三01:00~04:00每3分钟执行一次的crontab指令? A: 1,4 3 /bin/bash /home/sijiaomao/ok.sh B ...
- Java设置接口跨域
现在我们很多项目都是基于Java的REST结构风格前后端分离,在前端访问后端的时候就存在跨域,这个时候后端接口不处理就会存在访问不了.上代码! 1.创建一个Filter 在web.xml中配置 < ...
- 「技巧」如何快速安装 Sketch 插件
Sketch拥有强大丰富的插件,但是这些插件天各一方,四处查找下载地址非常麻烦.这里提供一个技巧,通过一个入口可以安装各种插件,基本涵盖了市面上所有靠谱的插件. 准备 Sketch54 Runner ...
- June. 25th 2018, Week 26th. Monday
Change in all things is sweet. 有改变就会有美好. From Aristole. Change is always good, but embracing change ...
- Storm入门(一)原理介绍
问题导读:1.hadoop有master与slave,Storm与之对应的节点是什么?2.Storm控制节点上面运行一个后台程序被称之为什么?3.Supervisor的作用是什么?4.Topology ...
- [LeetCode] 23. 合并K个排序链表
题目链接: https://leetcode-cn.com/problems/merge-k-sorted-lists/ 题目描述: 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂 ...
- 深蓝词库转换2.4版发布,支持最新的搜狗用户词库备份bin格式
很高兴的告诉大家,感谢GitHub上的h4x3rotab提供python版的搜狗用户词库备份bin格式的解析算法,感谢tmxkn1提供了C#版的实现,深蓝词库转换终于迎来了一个重大更新,能够支持搜狗用 ...
- DotNetCore 3.0 助力 WPF 开发
DotNetCore Is AnyWhere. 前言 Visual Studio 2019 已经正式发布了,DotNetCore 3.0 的正式版也指日可待.在之前的版本中,作为一名基于微软生态的传统 ...