• 自己实现HashMap


    实现简单版的HashMap

    只是将map的添加,查询,扩容实现了

    与JDK7源码中不同点,JDK中的hash函数是用到了很多的位运算,可以减少hash冲突,自己实现的HashMap只是简单利用了Object对象的hashCode函数

    这里的扩容参考了JDK中的方法,涉及到引用传递,多看几遍就懂了

    /**
     * 
     * table什么时候扩容的,threshold = capacity*loadfactor
     * 当size>threshold时,table扩容,数组长度增加为原长度的2倍,要重新计算hash值,重新把entry放入新的table中
     */
    public class MyHashMap {
    
        private Entry[] table;
        private int capacity = 16;
        private float loadfactor = 0.75f;
    
        private int size;
    
        public MyHashMap() {
            table = new Entry[capacity];
        }
    
        public void put(Object key, Object value) {
            Entry toAdd = new Entry(key, value);
            int index = key.hashCode() % table.length;
            Entry entry = table[index];
            if (entry == null) { // index这一行还没有放入entry时
                table[index] = toAdd;
                size++;
            } else {
                for (Entry e = entry; e != null; e = e.next) {
                    // 对于每一个Entry,先判断是不是要覆盖,也要判断是不是到了最后一个节点
                    if ((e.key.hashCode() == key.hashCode()) && (e.key == key || e.key.equals(key))) {
                        e.value = value;
                        break;
                    } else {
                        if (e.next == null) {
                            // 当前e是最后一个节点了 ,
                            // 将要添加的entry放在行首,他的next指向老的行首,
                            toAdd.next = table[index];
                            table[index] = toAdd;
                            size++;
                        }
                    }
                }
            }
            if (size > capacity * loadfactor) {
                resize(capacity << 1); // 左移一位,相当与乘以2
            }
        }
    
        private void resize(int newCapacity) {
            System.out.println("扩容了............");
            Entry[] newTable = new Entry[newCapacity];
            Entry[] src = table;
            for (int i = 0; i < src.length; i++) {
                Entry entry = src[i];
                if (entry != null) {
                    Entry e = entry;
                    do {
                        Entry nextEntry = e.next; // 先保存当前节点的下一个,做为循环判断条件
                        int index = e.key.hashCode() % newCapacity;
                        e.next = newTable[index];
                        // 针对e.next = newTable[index]这里用到了引用赋值(值传递)
                        // 当为新数组的每一行第一次赋值时,当newTable[index]为null时,将当前entry的next是指向null
                        // 下一行执行newTable[index] = e;并不会更改e.next的值
                        // 当newTable[index]不为null时,当前entry的next指向的是数组index行行首.这样将entry连接起来了
                        newTable[index] = e; // 将当前entry放在数组的index行的行首
                        e = nextEntry;
                    } while (e != null);
                }
            }
            table = newTable;
            capacity = newCapacity;
    
        }
    
        public Object get(Object key) {
            int index = key.hashCode() % table.length;
            Entry entry = table[index];
            for (Entry e = entry; e != null; e = e.next) {
                if (e.key.equals(key) || e.key == key) {
                    return e.value;
                }
            }
            return null;
        }
    
        public static void main(String[] args) {
            MyHashMap extHashMap = new MyHashMap();
            extHashMap.put("1号", "00");// 0
            extHashMap.put("2号", "00");// 1
            extHashMap.put("3号", "00");// 2
            extHashMap.put("4号", "00");// 3
            extHashMap.put("6号", "6号");// 4
            extHashMap.put("7号", "00");
            extHashMap.put("14号", "00");
            extHashMap.put("22号", "00");
            extHashMap.put("26号", "26号");
            extHashMap.put("27号", "00");
            extHashMap.put("28号", "00");
            extHashMap.put("66号", "00");
            extHashMap.put("26号", "^^^^^");
            extHashMap.print();
            System.out.println("============================");
            extHashMap.put("30号", "00");
            extHashMap.print();
            System.out.println(extHashMap.get("26号"));
    
        }
    
        public void print() {
            for (int i = 0; i < table.length; i++) {
                System.out.print("下标[" + i + "] ");
                for (Entry e = table[i]; e != null; e = e.next) {
                    System.out.print("【key = " + e.key + ",value = " + e.value + "");
                }
                System.out.println();
            }
    
        }
    
        class Entry {
            Object key;
            Object value;
            Entry next;
    
            public Entry(Object key, Object value) {
                this.key = key;
                this.value = value;
            }
    
        }
    }

    引用传递的例子

        @SuppressWarnings("unused")
        public static void main(String[] args) {
             User [] arr = new User[10];
             User u1  =  arr[0]; //引用传递也是值传递,u1指向了null对象
             arr[0]  =  new User("李四"); //给arr[0]赋值,即arr[0]指向了一个新的地址,这时u1还是null
             System.out.println();
        }
    
        static class User{
            String name;
            public User(String name) {
                super();
                this.name = name;
            }
        }
    }
  • 相关阅读:
    JS 页面生成锚点
    JavaScript AMD模块化规范
    Canvas文字的渲染基础 Better
    Canvas曲线绘制 Better
    clickhouse配置登录密码
    git pull 拉取报错:fatal: refusing to merge unrelated histories
    JAVA根据A星算法规划起点到终点二维坐标的最短路径
    JAVA使用netty建立websocket连接
    CSS设置文字超出部分自动换行
    SpringBoot(SpringMVC)使用addViewControllers设置统一请求URL重定向(映射、转发)配置
  • 原文地址:https://www.cnblogs.com/moris5013/p/11102317.html
Copyright © 2020-2023  润新知