前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java之手写HashMap(上)

Java之手写HashMap(上)

作者头像
用户5224393
发布2019-08-20 16:15:49
5110
发布2019-08-20 16:15:49
举报
文章被收录于专栏:Java研发军团Java研发军团

自定义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;
}

备注

以上都是写了大部分了,以上可能有问题希望大家看出来了多多指正,也可以私聊小编交流。其它方法了留在下一节再讲。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java研发军团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义HashMap
  • size()
  • put(K key, V value)
  • isEmpty()
  • get(Object key)
  • containsKey(K key)
  • 备注
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档