初学者第54节之自定义HashMap(上)

Posted Java研发军团

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初学者第54节之自定义HashMap(上)相关的知识,希望对你有一定的参考价值。

Java 猿程之家 免费分享
500G java  大型互联网项目视频
初学者第54节之自定义HashMap(上)
公告通知

本公众专注于为广大Java初学者和爱好者提供一个好的学习交流平台,不管你是编程大佬也好,还是编程小白也好,有问题都随时欢迎加小编微信咨询,小编都会在闲暇时候帮助大家解答工作和学习上遇到的问题,最重要也希望借助平台,多交一些朋友



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


✎备注

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

推荐阅读目录



扫码关注   有捣乱者绕道
长按,识别二维码,加关注

不存在任何培训机构招生信息!!

以上是关于初学者第54节之自定义HashMap(上)的主要内容,如果未能解决你的问题,请参考以下文章

初学者第二节之HelloWorld

初学者第55节自定义HashMap(下)

自定义SWT控件五之自定义穿梭框

Hadoop实战-Flume之自定义Source(十八)

Android 自定义View之自绘控件

( 转)Android之自定义适配器