程序员之手写HashMap,值得收藏

自定义HashMap
前面手写了MyArrayList以及MyLinkedList了,现在写的hashmap主要小编只采取数组加链表的方式来写了,那么现在就废话不多说了,还是和以前一样,现在就开始仿造HashMap里面的一部分方法吧。

size()
返回此映射中的键-值映射关系数。

 private int size;
    /**
    * 返回此映射中的键-值映射关系数。
    * 这个方法最简单了,直接定一个全局的size变量
    * 然后直接在size方法中获取即可
    * @return
    */
    public int size() {
     return this.size;
    }

put(K key, V value)

在此映射中关联指定值与指定键。

这个方法会在代码中将注释写清晰一点。当需要put的时候,肯定就跟元素挂钩了,那么我们说过hashmap是数组+链表组成的。

现在第一步需要有一个数组了,首先在创建数组之前我们都知道hashmap是键(key)值(value)队的形式储存的, 这个时候就需要创建一个储存key和value的类,这里使用内部类。

import java.util.Objects;
/**
* @author dcc
* 自定义hashmap,暂时按照自己的思路写个最简单的HashMap,适合新手。
*/
public class MyHashMap<K,V> {
 /**
 * 元素的总个数
 */
 private int size;
 /**
 * 数组默认长度
 */
 private static final int DEFAULT_LENGTH = 4;
 /**
 * 储存元素的数组
 */
 private Entry[] entries;
 /**
 * 默认构造
 */
 public MyHashMap() {
 this(DEFAULT_LENGTH);
 }
 /**
 * 有参构造
 * @param defaultLength
 */
 public MyHashMap(int defaultLength) {
 this.entries = new Entry[defaultLength];
 }
 /**
 * 返回此映射中的键-值映射关系数。
 * 这个方法最简单了,直接定一个全局的size变量
 * 然后直接在size方法中获取即可
 * @return
 */
 public int size() {
 return this.size;
 }
 /**
 * 当需要put的时候,肯定就跟元素挂钩了
 * 那么我们说过hashmap是数组+链表组成的。
 * 现在第一步需要有一个数组了
 * 首先在创建数组之前我们都知道hashmap是键(key)值(value)队的形式储存的
 * 这个时候就需要创建一个储存key和value的类,这里使用内部类
 * @param key
 * @param value
 * @return
 */
 public V put(K key, V value) {
 /**
 * 创建需要添加的元素
 */
 Entry<K,V> entry = new Entry<>(key,value);
 /**
 * 添加元素之前需要有一个数组,那么需要在全局定一个内部类的数组
 * 现在需要使用算法(key.hashcode()%entries.length)算出数据存在那个索引下。
 */
 int index = this.hash(key);
 /**
 * 判断数组该下标下是否有元素,如果有那么在判断是否key值一致
 * 一致则覆盖,否则就添加
 */
 if (Objects.isNull(this.entries[index])) {
 //表示没有数据,可以直接保存
 this.entries[index] = entry;
 this.size++;//这里表示新增一个元素
 }
 else
 {
 //添加到链表了
 this.entries[index].put(entry);
 }
 return value;
 }
 private int hash(K key) {
 return key.hashCode() % this.entries.length;
 }
 /**
 * 这是一个成员内部类
 * 储存hashmap元素的key和value
 */
 private class Entry<K,V> {
 /**
 * key 键
 */
 private K key;
 /**
 * value 值
 */
 private V value;
 /**
 * hash码,比较key是否重复使用
 */
 private long hash;
 /**
 * 数组+链表,所以就需要提供下个节点
 */
 private Entry<K,V> next;
 private Entry() {
 }
 /**
 * 构造器
 * @param key
 * @param value
 */
 private Entry(K key, V value) {
 this.key = key;
 this.value = value;
 this.hash = this.key.hashCode();
 }
 /**
 * 新增
 * @param entry
 */
 private void put(Entry<K, V> entry) {
 /**
 * 表示已经有了那么需要判断key是否一致
 */
 if (Objects.equals(this.key, entry.key) && this.hash == entry.hash) {
 //表示一致直接替换value值即可
 this.value = entry.value;
 } else {//表示可以新增了
 /**
 * 如果next中没有元素直接赋值了
 */
 if (Objects.isNull(this.next)) {
 this.next = entry;
 size++;//这里也表示为新增一个元素
 } else {//递归
 this.next.put(entry);
 }
 }
 }
 }
}

isEmpty()
如果此映射不包含键-值映射关系,则返回 true。

/**
* 判断是否有元素
* @return
*/
public boolean isEmpty() {
 return this.size > 0;
}

get(Object key)
返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。

外部类:

/**
* 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。
* @param key
* @return
*/
public V get(K key) {
 int index = this.hash(key);
 if (Objects.isNull(this.entries[index])) {
 return null;
 }
 Entry<K,V> entry = this.entries[index].get(key);
 return entry == null ? null : entry.value;
}

内部类

/**
* 获取数据
* @param key
* @return
*/
private Entry<K,V> get(K key) {
 //如果key都匹配直接返回当前value
 if (Objects.equals(key, this.key)) {
 return this;
 }
 //如果当前key不匹配则判断next节点是否为null,如果为null直接返回null
 if (Objects.isNull(this.next)) {
 return null;
 }
 //以上都不匹配就递归
 return this.next.get(key);
}

containsKey(K key)
如果此映射包含对于指定键的映射关系,则返回 true。

/**
* 如果此映射包含对于指定键的映射关系,则返回 true。
* @param key
* @return
*/
public boolean containsKey(K key) {
 int index = this.hash(key);
 return this.entries[index].get(key) != null;
}

备注
以上都是写了大部分了,以上可能有问题希望大家看出来了多多指正,也可以评论分享。

获取更多Java高级架构最新视频,
直接点击链接加群。https://jq.qq.com/?_wv=1027&k=5lXBNZ7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值