基于Java的HashMap和HashSet实现
一、Map接口类:
import java.util.Iterator; public interface IMap<K, V> {
/* 清除所有键值对 */
void clear(); /* key是否已经存在 */
boolean containsKey(K key); /* value是否存在 */
boolean containsValue(V value); /* 根据key获得value */
V get(K key); /* map是否为空 */
boolean isEmpty(); /* 所有key组成的数组 */
MyHashSet<K> keySet(); /* 存入键值对 */
void put(K key, V value); /* 把另外一个map中的所有键值对存入到当前map中 */
void putAll(IMap<? extends K, ? extends V> map); /* 根据key删除一个键值对 */
V remove(K key); /* 键值对的个数 */
int size(); /* 所有的value组成的数组 */
V[] values(); Iterator<MyHashMap.Node> iterator();
}
二、HashSet接口类:
import java.util.Iterator; public interface IHashSet<E> {
void add(E key); void remove(E key); void clear(); boolean contains(E key); boolean isEmpty(); int size(); Iterator<E> iterator();
}
三、HashMap类:
import java.util.Iterator; public class MyHashMap<K, V> implements IMap<K, V> {
private int length = 16; private Node[] buckets = new Node[length];// 桶
private int size; @Override
public void clear() {
for (int i = 0; i < buckets.length; i++) {
buckets[i] = null;
}
} @Override
public boolean containsKey(K key) {
int index = hash1(key);
if (buckets[index] == null) {
return false;
} else {
Node<K, V> p = buckets[index];// 相当于在链表中找key
while (p != null) {
K k1 = p.key;
// Java == 比较的是地址
// 借用java机制,hashcode和equals都来自于Object,用户可以改写这两个方法——制定对象相等的规则
if (k1 == key || (k1.hashCode() == key.hashCode() && k1.equals(key))) {
return true;
}
p = p.next;
}
} return false;
} @Override
public boolean containsValue(V value) {
for (int i = 0; i < buckets.length; i++) {
if (buckets[i] != null) {
Node<K, V> p = buckets[i];
while (p != null) {
if (p.value.equals(value))
return true;
}
}
}
return false;
} @Override
public V get(K key) {
int index = hash1(key);
if (buckets[index] == null) {
return null;
} else {
Node<K, V> p = buckets[index];
while (p != null) {
K k1 = p.key;
if (k1 == key || (k1.hashCode() == key.hashCode() && k1.equals(key))) {
return p.value;
}
p = p.next;
}
}
return null;
} @Override
public boolean isEmpty() {
return size == 0;
} @Override
public MyHashSet<K> keySet() {
MyHashSet<K> set = new MyHashSet<>();
for (int i = 0; i < buckets.length; i++) {
if (buckets[i] != null) {
Node<K, V> p = buckets[i];
while (p != null) {
set.add(p.key);
p = p.next;
}
}
}
return set;
} @Override
public void put(K key, V value) {
Node<K, V> node = new Node<>(key, value);
int index = hash1(key);// 算出在桶中的位置
if (buckets[index] == null) {// 桶中没有东西
buckets[index] = node;
size++;
} else {
Node<K, V> p = buckets[index];// 链表的表头找到
while (p != null) {
K k1 = p.key;
if (key == k1 || key.hashCode() == k1.hashCode() && key.equals(k1)) {
p.value = value;// 存在相同的key,则更新value
break;
}
if (p.next == null) {
p.next = node;
size++;
break;
}
p = p.next;
} }
} private int hash1(K key) {
// return key.hashCode() % length;
int h = 0;
int seed = 31;// 素数
String s = key.toString();
for (int i = 0; i != s.length(); ++i) {
h = seed * h + s.charAt(i);
}
return h % length;
} @Override
public void putAll(IMap<? extends K, ? extends V> map) { } @Override
public V remove(K key) {
int index = hash1(key);// 先定桶的位置
if (buckets[index] == null) {
return null;
} else {
Node<K, V> p = buckets[index];// 找到表头
Node<K, V> pre = p; while (p != null) {
K k1 = p.key;
if (k1.hashCode() == key.hashCode() && k1.equals(key)) {
// 移除
if (p == pre) {
buckets[index] = pre.next;
} else {
pre.next = p.next;
}
size--;
return p.value;
}
pre = p;
p = p.next;
}
}
return null;
} @Override
public int size() {
return size;
} @Override
public V[] values() {
return null;
} private class MapInterator implements Iterator<Node> {
int i = 0;
Node p = buckets[0]; @Override
public boolean hasNext() {
while (this.i < length && p == null) {
this.i++;
if (this.i == length)
p = null;
else
p = buckets[this.i];
}
// i是一个非空的桶,p是链表头
return p != null;
} @Override
public Node next() {
Node res = p;
p = p.next;
return res;
}
} @Override
public Iterator<Node> iterator() {
return new MapInterator();
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < buckets.length; i++) {
if (buckets[i] != null) {
Node<K, V> p = buckets[i];
while (p != null) {
sb.append("(" + p.key + "," + p.value + "),");
p = p.next;
}
}
}
return sb.toString();
} public class Node<K, V> {
public K key;
public V value; public Node(K key, V value) {
this.key = key;
this.value = value;
} private Node next; @Override
public String toString() {
return "BSTNode{" + "key=" + key + ", value=" + value + '}';
}
}
}
四、HashSet类:
import java.util.Iterator; public class MyHashSet<E> implements IHashSet<E> {
private MyHashMap<E, E> map = new MyHashMap<>(); @Override
public void add(E key) {
map.put(key, null);
} @Override
public void remove(E key) {
map.remove(key);
} @Override
public void clear() {
map.clear();
} @Override
public boolean contains(E key) {
return map.containsKey(key);
} @Override
public boolean isEmpty() {
return map.isEmpty();
} @Override
public int size() {
return map.size();
} @Override
public Iterator<E> iterator() {
Iterator<MyHashMap.Node> iter = map.iterator();
return new Iterator<E>() {
@Override
public boolean hasNext() {
return iter.hasNext();
} @Override
public E next() {
return (E) iter.next().key;
}
};
} @Override
public String toString() {
Iterator<MyHashMap.Node> iterator = map.iterator();
StringBuilder sb = new StringBuilder();
while (iterator.hasNext()) {
sb.append(iterator.next().key + ",");
}
return sb.toString();
}
}
五、HashMap优化:
1、扩容:如果当表中的75%已经被占用,即视为需要扩容了。
2、如果冲突造成的链表长度超过8的时候,就要转为红黑树存储。
3、hash函数优化。h = key.hashCode(); h^(h>>16); h % length。
基于Java的HashMap和HashSet实现的更多相关文章
- 【转】Java学习---HashMap和HashSet的内部工作机制
[原文]https://www.toutiao.com/i6593863882484220430/ HashMap和HashSet的内部工作机制 HashMap 和 HashSet 内部是如何工作的? ...
- [Java语言] HashMap,HashSet,Hashtable,Vector,ArrayList 的关系 <转>
这么几个比较常用的但是比较容易混淆的概念同出于 java.util 包.本文仅作几个类的浅度解析. (本文基于JDK1.7,源码来自openjdk1.7.) ├── Collection │ ├── ...
- 刷题upupup【Java中HashMap、HashSet用法总结】
HashMap: 常用操作 1. containsKey() 判断HashMap是否包含key 2. containsValue() 判断HashMap是否包含“值为value”的元素 3. get( ...
- java遍历hashMap、hashSet、Hashtable
一.遍历HashMap Map<Integer, String> map = new HashMap<Integer, String>(); 方法一:效率高 for(Entry ...
- Java set接口之HashSet集合原理讲解
Set接口 java.util.set接口继承自Collection接口,它与Collection接口中的方法基本一致, 并没有对 Collection接口进行功能上的扩充,只是比collection ...
- java该HashTable,HashMap和HashSet
同一时候我们也对HashSet和HashMap的核心方法hashcode进行了具体解释,见<探索equals()和hashCode()方法>. 万事俱备,那么以下我们就对基于hash算法的 ...
- java集合HashMap、HashTable、HashSet详解
一.Set和Map关系 Set代表集合元素无序,集合元素不可重复的集合,Map代表一种由多个key-value组成的集合,map集合是set集合的扩展只是名称不同,对应如下 二.HashMap的工作原 ...
- Java笔记(七)HashMap和HashSet
HashMap和HashSet 一)HashMap 1.Map接口 interface Map<K,V> { int size();//查看Map中的键值对个数 boolean isEmp ...
- Java 集合 HashMap & HashSet 拾遗
Java 集合 HashMap & HashSet 拾遗 @author ixenos 摘要:HashMap内部结构分析 Java HashMap采用的是冲突链表方式 从上图容易看出,如果选择 ...
随机推荐
- 使用javaScript操作页面元素
from selenium import webdriver import time import unittest from selenium.common.exceptions import We ...
- EF core的模型映射
在EF core里,可以通过实现IEntityTypeConfiguration来进行映射. 一.官网文档 https://docs.microsoft.com/en-us/ef/core/what- ...
- 华为AR2811配置脚本
华为AR28-11基本配置 # sysname Quidway # super password level simple admin --设置super用户password,级别,密码显示方式(明文 ...
- Mybaits入门使用
1.pom.xml配置信息 <dependencies> <dependency> <groupId>junit</groupId> <artif ...
- SpringMVC是怎么工作的,SpringMVC的工作原理
SpringWeb MVC 是怎么工作的,SpringMVC的原理,SpringMVC源码 分析. 介绍 SpringWeb MVC是Spring Framework中的一部分,当我们需要使用spri ...
- 关于pom.xml文件中引入net.sf.json-lib出错问题
关于pom.xml文件中引入net.sf.json-lib出错问题 在项目中引入以下依赖时一直报错 <dependency> <groupId>net.sf.json-lib& ...
- 2017GCTF部分writeup
0x00:热身题 渗透测试大法:第一招,扫端口:第二招,... . 扫后台试试呗,用御剑扫到存在robots.txt,访问发现很多个Disallow:可能的试试,发现flag在/rob0t.php中 ...
- 027 storm面试小题
1.大纲 Storm工作原理是什么? 流的模式是什么?默认是什么? 对于mapreduce如何理解? Storm的特点和特性是什么? Storm组件有哪些? 2.Storm工作原理是什么? 相对于ha ...
- SpringBoot的自动配置原理
一.入口 上篇注解@SpringBootApplication简单分析,说到了@SpringBootApplication注解的内部结构, 其中@EnableAutoConfiguration利用En ...
- unity runtime时导入fbx文件
TriLib is a Unity model loader package designed to allow the user to load various 3D model formats i ...