手写识别底层原理_java入门必看--HashMap底层原理和手写HashMap

3.1 HashMap的原理

• 底层结构是哈希表,采用了顺序表+链表结合结构;同一个链表的上所有元素的存储地址都是相同的,是发生冲突的元素

86845a2cb560cfd06cc43fdd2b33cab4.png

• 链表上每个节点的就是一个Entry,字段包括四部分

0154e3277b51dcd6f9053b09c2a9ce3b.png

问:同一个链表上节点的哈希码相同吗??哈希码可能不相同,存储地址相同。

• 哈希表的优点

• 添加快、查询快(通过计算得到存储位置,不是通过比较)

• 无序

• (key)唯一

• 关键参数

• 默认主数组长度16;

• 默认装填因子0.75。

• 每次主数组扩容为原来的2倍

• JDK8,当链表长度大于8,链表变成红黑树

bafed8194b6883086c27af27bae9f9a0.png

• 第一步计算哈希码,不仅调用了hashCode(),有进行了多次散列。目的在于key不同,哈希码尽量不同,减少冲突

final int hash(Object k) {
 int h = 0;
    h ^= k.hashCode();
    h ^= (h >>> 20) ^ (h >>> 12);
 return h ^ (h >>> 7) ^ (h >>> 4);
}

• 细节:发生冲突,经过比较不存在相同key的元素,要添加一个新的节点。不是加到链表最后,而是添加到链表最前

fdf3f25c22cfb2e44ad76381630bfb94.png

009a75ab1bc3d35079305b7bd8b119bd.png

3.2定义Map接口

【示例11】 定义Map接口

public interface Map {
 //定义方法
 public void put(Object key,Object value);
 public Object get(Object key);
 public int size();
 public boolean isEmpty();
 //定义内部接口
 interface Entry{
 public Object getKey();
 public Object getValue();
    }
}

3.3手写HashMap

【示例12】 手写HashMap

public class HashMap implements Map {
 public Entry[] table;//指向哈希表的数组引用
 int size;//键值对的数量
 public HashMap() {
 table = new Entry[11];//哈希表主数组默认长度16
 }
 public void put(Object key, Object value) {
 //计算哈希码
 int hash = key.hashCode();
 //根据哈希码计算存储位置
 int index = hash % table.length;
 //存入指定位置
 if (table[index] == null) {//如果该位置没有元素,增加一个节点
 table[index] = new Entry(hash, key, value);
 size++;
        } else {//如果有元素,进行逐个比较
 Entry entry = table[index];
 //Entry previousEntry = null;
 while (entry != null) {
 //如果找到了相同的key
 if (entry.getKey().equals(key)) {
 //新的value替代旧的value
 entry.value = value;
 return;
                }
 //previousEntry = entry;
 entry = entry.next;
            }
 //循环结束,表明也没有相同的key,在链表最后添加一个节点
 //previousEntry.next = new Entry(hash, key, value);
            //循环结束,表明也没有相同的key,在链表最前边添加一个节点
 Entry firstEntry = table[index];
 table[index] = new Entry(hash, key, value,firstEntry);
 size++;
        }
    }
 public Object get(Object key) {
 //计算哈希码
 int hash = key.hashCode();
 //根据哈希码计算存储位置
 int index = hash % table.length;
 //查找对应的Entry
 Entry entry = null;
 if (table[index] != null) {
            Entry currentEntry = table[index];
 while (currentEntry != null) {
 if (currentEntry.getKey().equals(key)) {
                    entry = currentEntry;
 break;
                }
                currentEntry = currentEntry.next;
            }
        }
 return entry == null ? null : entry.getValue();
    }
 public String toString() {
        StringBuilder builder = new StringBuilder("{");
 for(int i=0;i<table.length;i++){
 if(table[i] != null){
                Entry entry = table[i];
 while(entry != null){
             builder.append(entry.getKey()+"="+entry.getValue()+",");
                    entry = entry.next;
                }
            }
        }
 if(builder.length()!=1){
            builder.deleteCharAt(builder.length()-1);
        }
        builder.append("}");
 return builder.toString();
    }
 public int size() {
 return size;
 public boolean isEmpty() {
 return size == 0;
    }
 class Entry implements Map.Entry {
 private int hash;//哈希码
 private Object key;//键
 private Object value;//值
 private Entry next;//指向下一个节点的指针
 public Entry() {
        }
 public Entry(int hash, Object key, Object value) {
 this.hash = hash;
 this.key = key;
 this.value = value;
        }
 public Entry(int hash, Object key, Object value, Entry next) {
 this.hash = hash;
 this.key = key;
 this.value = value;
 this.next = next;
        }
 public Object getKey() {
 return key;
        }
 public Object getValue() {
 return value;
        }
 public String toString() {
 if (next != null) {
 return "{" + key + ":" + value + "-" + hash + " " + next + "}";
            } else {
 return "{" + key + ":" + value + "-" + hash + "}";
            }
        }
    }
}

1.4 测试HashMap

【示例13】 测试HashMap

public class TestHashMap {
 public static void main(String[] args) {
        java.util.HashMap  map2;
        HashMap map = new HashMap();
        map.put(23,"China");
        map.put(36,"Japan");
        map.put(48,"America");
        map.put(86,"the United States");
        map.put(67,"France");
        map.put(23,"Italian");
        map.put(47,"England");
        System.out.println(map.size());
        System.out.println(Arrays.toString(map.table));
        System.out.println(map);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值