实现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 类. 这些 ...
随机推荐
- ILRuntime入门笔记
基础知识 官方地址:https://github.com/Ourpalm/ILRuntime 官方文档:https://ourpalm.github.io/ILRuntime/ 文档Markdown源 ...
- 周一02.4变量&垃圾回收机制
一.变量 1. 什么是变量 量:记录事物的某种状态,即事物典型的特征 变:事物的状态是可以发生变化的 2. 为何要用变量 是为了让计算机能够像人一样记录事物的状态 3. 如何用变量 (先定义后引用) ...
- pyspider 初次使用
一 安装 pip install pyspider 请安装PhantomJS:http://phantomjs.org/build.html 二 检验是否启动成功 cmd中输入: pyspider 安 ...
- Kafka Frequently Asked Questions
This is intended to be an easy to understand FAQ on the topic of Kafka. One part is for beginners, o ...
- 去掉所有的html标签,得到HTML标签中的所有内容
text——含有HTML标签的字符串 var text1=text.replace(/<\/?.+?>/g,""); text=text1.replace(/ /g,& ...
- 第一课android开发之在activity间传递参数
一.活动间简单参数传递:1.在布局中添加按钮,用<Button,用id设置id名称,id="@+id/这儿填写你要设置成的名称":用text设置按钮上显示的文字.text=& ...
- html页面打开ie浏览器默认打开最高版本
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
- ReSharper2018破解详细方法
下载地址: 主程序官网下载链接:https://download.jetbrains.com/resharper/ReSharperUltimate.2018.3.3/JetBrains.ReShar ...
- kvm虚拟化介绍
一.虚拟化分类 1.虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机.在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互相 ...
- HTML基础知识个人总结
[学习的网站是主要是W3school,还加上一些其他搜索学习到的内容,仅在博客做个人整理] 一.标签——尖括号围成的关键词,成对出现. ※使用时必须符合标签嵌套规则 1. (1) <!DOCTY ...