一、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实现的更多相关文章

  1. 【转】Java学习---HashMap和HashSet的内部工作机制

    [原文]https://www.toutiao.com/i6593863882484220430/ HashMap和HashSet的内部工作机制 HashMap 和 HashSet 内部是如何工作的? ...

  2. [Java语言] HashMap,HashSet,Hashtable,Vector,ArrayList 的关系 <转>

    这么几个比较常用的但是比较容易混淆的概念同出于 java.util 包.本文仅作几个类的浅度解析. (本文基于JDK1.7,源码来自openjdk1.7.) ├── Collection │ ├── ...

  3. 刷题upupup【Java中HashMap、HashSet用法总结】

    HashMap: 常用操作 1. containsKey() 判断HashMap是否包含key 2. containsValue() 判断HashMap是否包含“值为value”的元素 3. get( ...

  4. java遍历hashMap、hashSet、Hashtable

    一.遍历HashMap Map<Integer, String> map = new HashMap<Integer, String>(); 方法一:效率高 for(Entry ...

  5. Java set接口之HashSet集合原理讲解

    Set接口 java.util.set接口继承自Collection接口,它与Collection接口中的方法基本一致, 并没有对 Collection接口进行功能上的扩充,只是比collection ...

  6. java该HashTable,HashMap和HashSet

    同一时候我们也对HashSet和HashMap的核心方法hashcode进行了具体解释,见<探索equals()和hashCode()方法>. 万事俱备,那么以下我们就对基于hash算法的 ...

  7. java集合HashMap、HashTable、HashSet详解

    一.Set和Map关系 Set代表集合元素无序,集合元素不可重复的集合,Map代表一种由多个key-value组成的集合,map集合是set集合的扩展只是名称不同,对应如下 二.HashMap的工作原 ...

  8. Java笔记(七)HashMap和HashSet

    HashMap和HashSet 一)HashMap 1.Map接口 interface Map<K,V> { int size();//查看Map中的键值对个数 boolean isEmp ...

  9. Java 集合 HashMap & HashSet 拾遗

    Java 集合 HashMap & HashSet 拾遗 @author ixenos 摘要:HashMap内部结构分析 Java HashMap采用的是冲突链表方式 从上图容易看出,如果选择 ...

随机推荐

  1. 中小学Python编程语言教学

    中小学Python编程语言教学 作为一名高中信息技术老师,被技术的发展潮流推动着,不断更新教学内容和方法,以适应快速发展的信息社会. 以前的中小学信息技术课程,老师们各显神通,身怀绝技,教PS,Fal ...

  2. 用JDBC连接SQL Server2017数据库

    用JDBC连接SQL Server2017数据库 2018年03月26日 17:40:47 yasinzhang 阅读数:8346 安装完SQL server2017之后,选择SQL 身份验证登录,可 ...

  3. 前端开发,走浏览器缓存真的很烦,拒绝浏览器走缓存从meta标签做起!

    <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv ...

  4. git 随笔(随时更新)

    w:跳到下个词前面, e:跳到下个词后面,b是跳到上一个单词前面. v:选择 ,可以批量操作 q + a:  录制宏, a 是存录制地方,q录制完毕. @a :执行录制操作. @a 前面➕数字:例如1 ...

  5. C# 调用继电器api usb_relay_device.dll

    C# 调用继电器api usb_relay_device.dll 代码封装 usb_relay_device.dll 为C++编写 using System; using System.Collect ...

  6. 【Linux】在Win10上搭建WSL(适用于Linux的Windows子系统)

    1.打开WSL  ,控制面板 -- 程序 -- 程序和功能 -- 打开或关闭Windows功能 - 选中[适用于Linux的Windows子系统] 2.开启后重启电脑 3.在Win10自带的Micro ...

  7. vs2017更新出错:The entire Box execution exiting with result code: 0x0

    在将vs2017 15.7.4更新至15.9.5出现“The entire Box execution exiting with result code: 0x0”错误,也就是文件解压下载开始安装后, ...

  8. nginx代理tcp协议连接mysql

    阅读目录 一.mariadb安装及配置 1.1 在192.168.182.155安装mariadb 1.2 配置MariaDB的字符集 1.3  添加用户,设置权限 1.4 防火墙设置 二.nginx ...

  9. 记一次Hbase的行键过滤器事故问题

    数据总数:746条数据 因为后面需要进行算法合成,而且spark目前对这种算法支持并不好,因此采用代码编写,所以在查询hbase的过程中采用的是java直接查询, 但是为了加快查询速度,我尽可能的使用 ...

  10. pygame学习之绘制移动的矩形

    import pygame from pygame.locals import * pygame.init() screen = pygame.display.set_mode((600, 500)) ...