首页 > 其他分享 >手写HashMap JDK1.7(无红黑树)

手写HashMap JDK1.7(无红黑树)

时间:2023-05-02 23:11:15浏览次数:44  
标签:无红 黑树 HashMap index int current null public hashMap

public interface MyMap <K,V>{

    V get(K k);
    V put(K k, V v);
    int size();
    V remove(K k);
    boolean isEmpty();
}
package main.java.com.hashmap;

public class MyHashMap <K, V> implements MyMap<K, V>{

    final static int DEFAULT_CAPACITY = 16;
    final static float DEFAULT_LOAD_FACTORY = 0.75f;

    private  int capacity;
    private float loadFactor;
    private int size = 0;

    Entry<K,V>[] table;

    public MyHashMap() {
        this(DEFAULT_CAPACITY,DEFAULT_LOAD_FACTORY);
    }

    public MyHashMap(int capacity, float loadFactor){
        this.capacity = upperMinPowerOf2(capacity);     //获取为2的幂次方的容量大小
        this.loadFactor = loadFactor;                  //加载因子,用于扩容,本次实现中尚未用到该字段
        this.table = new Entry[capacity];
    }

    private int upperMinPowerOf2(int capacity) {
        int power = 1;
        while (power <= capacity){
            power *= 2;
        }
        return power;
    }

    @Override
    public V get(K k) {
        int index = k.hashCode() % table.length;
        Entry<K, V> current = table[index];
        //遍历链表直至找到相同的hashcode
        while(current != null){
            if(current.k == k){
                return current.v;
            }
            current = current.next;
        }
        return null;
    }

    @Override
    public V put(K k, V v) {
        // 通过k换算hashcode取模绑定数组位置
        int index = k.hashCode() % table.length;
        Entry<K,V> current = table[index];
        //如果index下没有绑定元素,则直接头插法
        if(current == null){
            table[index] = new Entry<K,V>(k,v,null);
            size ++;
            return null;
        }
        //如果index下有元素
        if(current != null){
            while(current != null){
                if(current.k == k){
                    V oldValue = current.v;
                    current.v = v;
                    return oldValue;
                }
                current = current.next;
                table[index] = new Entry<K,V>(k,v,table[index]);
                size ++;
                return null;
            }
        }
        return null;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public V remove(K k) {
        int index = k.hashCode() % table.length;
        Entry<K, V> current = table[index];
        V result = null;
        Entry<K,V> pre = null;

        while(current != null){
            if(current.k == k){
                result = current.v;
                size --;
                if(pre!=null){
                    pre.next = current.next;
                }else{
                    table[index] = current.next;
                }
                return result;
            }
            //向下遍历
            pre = current;
            current = current.next;
        }
        return null;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    class Entry<K, V>{
        K k;
        V v;
        Entry<K,V> next;

        public Entry(K k, V v, Entry<K, V> next) {
            this.k = k;
            this.v = v;
            this.next = next;
        }
    }
}
package main.java.com.hashmap;

public class HashMapTest {

    public static void main(String[] args) {
        MyHashMap<Integer, Integer> hashMap = new MyHashMap<>();
        hashMap.put(1,101);
        hashMap.put(2,202);
        hashMap.put(3,303);
        hashMap.put(1,111);

        int[] keys = new int[]{1,2,3};
        for (int i = 0; i < keys.length; i++) {
            System.out.println(keys[i]+"---"+hashMap.get(keys[i]));
        }

        hashMap.remove(1);
        hashMap.remove(3);
        System.out.println("hashMap size:"+hashMap.size());
        System.out.println(1+": "+hashMap.get(1));
        System.out.println(3+": "+hashMap.get(3));
        System.out.println(2+": "+hashMap.get(2));
    }
}

理解:

HashMap在JDK1.8之前是数组+链表的数据结构,比如数组长度是10 (默认长度是1<<4 16), 在put存储的时候会将key换算成hashcode,并取模length的余数 0~9之间,以便于分散在数组的各个下标中;

而1%10和 11%10 的余数都是1,这种情况下会产生哈希碰撞也叫哈希冲突,1.7中才用单向链表存储这类数据,并使用头插法,查到链表的头部,而其余的元素向下移动一位;

当map中元素过多,且大于数组的75%时,数组会扩容 2的N次幂,此时,比如数组长度由10变成了20,那么取模的范围变成0~19,所有10以上的元素位置发生了变化重新计算位置也就是再哈希,其map在重新计算位置时,查询或者插入的效率会有抖动。

JDK1.8以后,hashmap是数组+链表+红黑树,对查询效率,时间复杂度进行了优化,也就是说 在 n>8 时 查询效率由n/2 优化为了 olog(n),之所以还有8位的链表,是因为n<8时,n/2 的效率是大于 olog(n)的

标签:无红,黑树,HashMap,index,int,current,null,public,hashMap
From: https://www.cnblogs.com/charkey/p/17368498.html

相关文章

  • rust 更新HashMap
    在更新HashMap的时候,有以下几个常见的情况fnmain(){usestd::collections::HashMap;letmutscores=HashMap::new();scores.insert("Blue",10);//覆盖已有的值,返回一个Option类型,返回旧的值letold=scores.insert("Blue",20);assert_e......
  • HashMap的数组长度为何必须是2的n次方
    扩容方便,数字位移计算方便效率高;计算元素下标使用的方式是key的hash&(数组length-1),由于length是2^n,转换成二进制后2^-1最低位就全部都是1,比如111,就相当于是数组长度的掩码,那么hash&111就可以将数组的每一位都覆盖,加入数组长度不是2^n,那么length-1低位不全是1,比如101,那么h......
  • HashMap为什么存在线程不安全呢?
    关注Java后端技术栈“回复“面试”获取最新资料本文主要探讨下HashMap在多线程环境下容易出现哪些问题,深层次理解其中的HashMap。我们都知道HashMap是线程不安全的,但是HashMap在咱们日常工作中使用频率在所有map中确实属于比较高的。因为它可以满足我们大多数的场景了。上面展示了......
  • List与HashMap区别,key,value,感谢火龙果,dgqbcht,awusoft帮助
    首先要感谢不想要妮称,dgqbcht,awusoft友情帮助Map是一个映射,是key-value值对.Map在java1.0以后进行了修改,使其能够与普通的集合相融.在Map的内部定义了内部接口Entry,主要就是要讲key和value以集合(Set)的形式来体现.List是集合的一个分支,是一个接口.List中的元素有顺序(输......
  • 4月24日红黑树插入实现
    继搜索二叉树和AVL树后有了红黑树。AVL树改善了搜索二叉树在极端情况下的严重效率退化,但是在运用得过程中发现他对平衡的要求几乎达到了苛刻的地步,往往经过一系列复杂的变化只是将树的深度优化了一点点,而这一点点在现在日益快速的处理器下根本不起眼,于是有了更优的结构红黑树:红......
  • 红黑树笔记
    (本人笔记潦草,估计只有我能看懂,保存给自己看,不代表肯定让其他人能理解)附上源码笔记://SPDX-License-Identifier:GPL-2.0-or-later/*RedBlackTrees(C)1999AndreaArcangeli<[email protected]>(C)2002DavidWoodhouse<[email protected]>(C)2012Mi......
  • HashMap 以及多线程基本感念
     接口Map:映射项,(键值对)的容器注意: 键是唯一的 值是可以重复的实现类HashMap :哈希表结构允许使用null值和null键线程不安全键唯一无序 linkedHashMap: 保证插入顺序和迭代顺序一致 Hashtable:数据结构:哈希表不允许使用nullnull值和null键,线程安全 ......
  • 如何遍历HashMap集合?
    在Java中,HashMap是一种常用的数据结构,它提供了快速的查找、插入和删除操作。当我们需要遍历HashMap中的所有元素时,可以利用三种不同的方法实现。方法一:使用键值对遍历HashMap中存储的是键值对的形式,因此最简单的方法就是直接遍历键值对。我们可以通过以下代码实现://创建一个Ha......
  • 红黑树
    参考:https://juejin.cn/post/6844903519632228365https://zhuanlan.zhihu.com/p/143585797引入先了解二叉查找树如果左子树不为空,则左子树上所有节点的值均小于根节点的值如果右子树不为空,则右子树上所有节点的值均大于根节点值左右子树也都是二叉查找树 二分查找的......
  • 《面试1v1》HashMap
    没有人比中国人更懂HashMap我是javapub,一名Markdown程序员从......