hashmap简单实现
p.p1 { margin: 0; font: 11px Monaco }
p.p2 { margin: 0; font: 11px Monaco; min-height: 15px }
p.p3 { margin: 0; font: 11px Monaco; color: rgba(79, 118, 203, 1) }
p.p4 { margin: 0; font: 11px Monaco; color: rgba(147, 26, 104, 1) }
p.p5 { margin: 0; font: 11px Monaco; color: rgba(119, 119, 119, 1) }
p.p6 { margin: 0; font: 11px Monaco; color: rgba(126, 80, 79, 1) }
p.p7 { margin: 0; font: 11px Monaco; color: rgba(78, 144, 114, 1) }
span.s1 { color: rgba(147, 26, 104, 1) }
span.s2 { color: rgba(145, 175, 203, 1) }
span.s3 { text-decoration: underline; color: rgba(145, 175, 203, 1) }
span.s4 { text-decoration: underline }
span.s5 { color: rgba(0, 0, 0, 1) }
span.s6 { color: rgba(3, 38, 204, 1) }
span.s7 { color: rgba(126, 80, 79, 1) }
span.s8 { color: rgba(78, 144, 114, 1) }
span.Apple-tab-span { white-space: pre }
import java.util.AbstractMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
/**
记得很早之前看到过一篇帖子 说一个面试者去面试 某大厂要他当场写一个hashmap,其实今天讲的这个例子,足以应付那场面试,核心思想一应俱全,有些地方还欠完善。。。
这个simpleHashmap原理是如下实现
put:
首先定义一个基于链表的Entry hash桶数组
通过key的hashcode取模数组大小得到对应的hash桶下标
如果链表中没有找到对应的key 则加入当前hash桶中
否则覆盖Entry对象
get:
1.通过key的hashcode取模数组大小得到对应的hash桶
判断hash桶中是否存在Entry对象 有取出;没有返回null.
<br>
以下是实际hashmap实现思路:
以Entry[]数组实现的哈希桶数组,用Key的哈希值取模桶数组的大小可得到数组下标。
插入元素时,如果两条Key落在同一个桶(比如哈希值1和17取模16后都属于第一个哈希桶),我们称之为哈希冲突。
JDK的做法是链表法,Entry用一个next属性实现多个Entry以单向链表存放。查找哈希值为17的key时,先定位到哈希桶,然后链表遍历桶里所有元素,逐个比较其Hash值然后key值。
在JDK8里,新增默认为8的阈值,当一个桶里的Entry超过閥值,就不以单向链表而以红黑树来存放以加快Key的查找速度。
当然,最好还是桶里只有一个元素,不用去比较。所以默认当Entry数量达到桶数量的75%时,哈希冲突已比较严重,就会成倍扩容桶数组,并重新分配所有原来的Entry。扩容成本不低,所以也最好有个预估值。
取模用与操作(hash & (arrayLength-1))会比较快,所以数组的大小永远是2的N次方, 你随便给一个初始值比如17会转为32。默认第一次放入元素时的初始值是16。
iterator()时顺着哈希桶数组来遍历,看起来是个乱序
*
*
*/
public class SimpleHashMap<K, V> extends AbstractMap<K, V> {
static final int SIZE = 997;
LinkedList<MapEntry<K, V>>[] buckets = new LinkedList[SIZE];
@Override
public V put(K key, V value) {
V oldValue = null;
int index = Math.abs(key.hashCode()) % SIZE;// 取模
if (buckets[index] == null) {
buckets[index] = new LinkedList<MapEntry<K, V>>();
}
LinkedList<MapEntry<K, V>> bucket = buckets[index];// 桶位【槽位】
MapEntry<K, V> pair = new MapEntry<K, V>(key, value);
boolean found = false;
ListIterator<MapEntry<K, V>> it = bucket.listIterator();
while (it.hasNext()) {
MapEntry<K, V> iPair = it.next();
if (iPair.getKey().equals(key)) {
oldValue = iPair.getValue();
it.set(pair);
found = true;
break;
}
}
if (!found) {
bucket.add(pair);
}
return oldValue;
}
@Override
public V get(Object key) {
int index = Math.abs(key.hashCode()) % SIZE;
if (buckets[index] == null) {
return null;
}
for (MapEntry<K, V> iPair : buckets[index]) {
if (iPair.getKey().equals(key)) {
return iPair.getValue();
}
}
return null;
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
Set<Map.Entry<K, V>> set = new HashSet<Map.Entry<K, V>>();
for (LinkedList<MapEntry<K, V>> bucket : buckets) {
if (bucket == null) {
continue;
}
for (MapEntry<K, V> mpair : bucket) {
set.add(mpair);
}
}
return set;
}
public static void main(String[] args) {
// SimpleHashMap<String, String> simpleHashMap=new SimpleHashMap<String,String>();
// simpleHashMap.putAll(Countries.capitals(25));
// System.out.println(simpleHashMap);
// System.out.println(simpleHashMap.get("ERITREA"));
// System.out.println(simpleHashMap.entrySet());
System.out.println(1 ^ 1); // 两个二进制比较 相同取0 不同为一
}
}
hashmap简单实现的更多相关文章
- JVM&NIO&HashMap简单问
JVM&NIO&HashMap简单问 背景:前几天在网上看到关于JVM&NIO&HashMap的一些连环炮的面试题,整理下以备不时之需. 一.JVM Java的虚拟机的 ...
- 哈希表原理及hashmap简单实现
哈希表也叫做散列表.在各种语言中都有hashmap的实现.其最突出的优点是查找和插入以及删除具有常数的时间复杂度 我们可以把哈希表理解为数组+链表 数组具有常数复杂度的查找,为什么呢,因为数组是在内存 ...
- HashMap简单介绍
哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表. 一.什么是哈希表 在讨论哈希表之 ...
- HashMap简单理解
1. hashmap基于哈希表的map接口实现,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable ...
- hashmap简单实例(个人使用经验)
一.HashMap<int,String>是错误的:因为int是基本类型,而key和value要求是对象,所以要用Integer而不是int.HashMap<String,Objec ...
- java集合框架(1) hashMap 简单使用以及深度分析(转)
java.util 类 HashMap<K,V>java.lang.Object java.util.AbstractMap<K,V> java.util.Hash ...
- java集合框架 hashMap 简单使用
参考文章:http://blog.csdn.net/itm_hadf/article/details/7497462 通常,默认加载因子 (.75) 在时间和空间成本上寻求一种折衷. 加载因 ...
- 关于Android中ArrayMap/SparseArray比HashMap性能好的深入研究
由于网上有朋友对于这个问题已经有了很详细的研究,所以我就不班门弄斧了: 转载于:http://android-performance.com/android/2014/02/10/android-sp ...
- 【Java】HashMap源码分析——基本概念
在JDK1.8后,对HashMap源码进行了更改,引入了红黑树.在这之前,HashMap实际上就是就是数组+链表的结构,由于HashMap是一张哈希表,其会产生哈希冲突,为了解决哈希冲突,HashMa ...
随机推荐
- Spring Cloud 学习 (七) Spring Cloud Sleuth
微服务架构是一个分布式架构,微服务系统按业务划分服务单元,一个微服务系统往往有很多个服务单元.由于服务单元数量众多,业务的复杂性较高,如果出现了错误和异常,很难去定位.主要体现在一个请求可能需要调用很 ...
- 0001_20190327_使用frp搭建内网穿透
1. 环境 a) 公网服务器为阿里云的ECS Windows 2008 R2服务器, 有公网IP地址; 这个作为frp的服务器 b) 内网是开发服务器, Cento ...
- Django结合Websocket进行WebSSH的实现
什么是webssh? 泛指一种技术可以在网页上实现一个 终端.从而无需 之类的模拟终端工具进行 连接,将 这一比较低层的操作也从 架构扭成了 架构 这样的架构常用在运维制作开发一些堡垒机等系统中,或是 ...
- Python中sorted(iterable, *, key=None, reverse=False)函数参数定义中的独立星号(*)的含义
老猿在 <Python中函数的参数带星号是什么意思?>中介绍了Python函数中参数带星号的含义,而在实际使用和Python的标准文档中,会看到某写函数(如sorted(iterable, ...
- PyQt(Python+Qt)学习随笔:PyQt界面派生类构造方法中super方法的使用
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在<第15.7节 PyQt入门学习:PyQt5应用构建详细过程介绍>和订阅专栏<第 ...
- PyQt(Python+Qt)学习随笔:布局控件layout的LeftMargin等contentsMargins属性
在Qt Designer中布局控件有4个,分别是Vertical Layout(垂直布局).Horizontal Layout(水平布局).Grid Layout(网格布局).Form Layout( ...
- SQL注入WAF绕过姿势
(1)大小写绕过 此类绕过不经常使用,但是用的时候也不能忘了它,他原理是基于SQL语句不分大小写的,但过滤只过滤其中一种. 这里有道题 (2)替换关键字 这种情况下大小写转化无法绕过而且正则表达式会替 ...
- 在 GitHub 玩硬件——GitHub 热点速览 Vol.49
作者:HelloGitHub-小鱼干 本周的 GitHub Trending 可以说是非常之硬核,天才少年稚晖君的 2 个硬件变装项目荣登热点榜,看完将充电宝改装为显示器的视频,搭配 HDMI-PI ...
- 返回sourceString 中出现的第一个 searchString 的索引
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- P4317 花神的数论题,关于luogu题解粉兔做法的理解
link 题意 设 \(\text{sum}(i)\) 表示 \(i\) 的二进制表示中 \(1\) 的个数.给出一个正整数 \(N\) ,求 \(\prod_{i=1}^{N}\text{sum}( ...