基于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采用的是冲突链表方式 从上图容易看出,如果选择 ...
随机推荐
- 团队软件的NABCD——星遇
日期:2019.4.17 博客期:053 星期三 我们项目是个面向希望有新奇体验的用户的社交软件,致力于打造不一样的有趣的社交. N:(Need,需求) 目前主流社交软件由于时间原因体量越来越大,各种 ...
- 2018开源中国最受欢迎的中国软件MyBatis-Plus
2018开源中国最受欢迎的中国软件MyBatis-Plus 官方网址:https://mp.baomidou.com 中国软件,中文文档 什么是MyBatis-Plus? 进入官方第一句话:为简化开发 ...
- 解决svn更新项目目录时“Error:svn: E155037: Previous operation has not finished; run 'cleanup' if it was interrupted”的报错问题
今天在IDEA更新项目目录时,发现报错“Error:svn: E155037: Previous operation has not finished; run 'cleanup' if it was ...
- 论文阅读笔记五十一:CenterNet: Keypoint Triplets for Object Detection(CVPR2019)
论文链接:https://arxiv.org/abs/1904.08189 github:https://github.com/Duankaiwen/CenterNet 摘要 目标检测中,基于关键点的 ...
- 1到n的最小步数
1到n的最小步数 Time Limit: 1 Sec Memory Limit: 128 MB 给你一个数n,让你求从1到n的最小步数是多少. 对于当前的数x有三种操作: 1: x+1 2: x ...
- pg数据库查询表大小
查询单个表 select pg_size_pretty(pg_relation_size('table_name')); 按size大小排序列出所有表 SELECT table_schema || ' ...
- 数据分析入门——Pandas类库基础知识
使用python进行数据分析时,经常会用Pandas类库处理数据,将数据转换成我们需要的格式.Pandas中的有两个数据结构和处理数据相关,分别是Series和DataFrame. Series Se ...
- DbHelperSQL 增加事务处理方法(2种)
方法一: 1 public static bool ExecuteSqlByTrans(List<SqlAndPrams> list) { bool success = true; Ope ...
- c语言博客作业--结构体&文件
1.本章学习总结 1.1思维导图 1.2.本章学习体会 本章学到了结构体如何构建,用typedef进行重定义结构体,结构指针,访问结构体的方式等. 文件:文件的读取,文件读写的几个函数,基本了解了文本 ...
- 【省选十连测之九】【DP】【组合计数去重】【欧拉函数】基本题
目录 题意: 输入格式: 输出格式: 数据范围: 思路: 嵌套题的转移 基本题的转移 Part1 Part2 Part3 代码 题意: 这是一个关于括号组合的题. 首先定义一道题是由'(',')',' ...