HashMap java代码实现

150 阅读4分钟

HashMap java代码实现

先上代码

package MyDataStructures.散列;

import java.util.Map;

public interface MyMap<K, V> {
    public void clear();

    public boolean containsKey(K key);

    public boolean containsValue(V value);

    public java.util.Set<Entry<K, V>> entrySet();

    public V get(K key);

    public boolean isEmpty();

    public java.util.Set<K> keySet();

    public V put(K key, V value);

    public void remove(K key);

    public int size();

    public java.util.Set<V> vlaues();

    public static class Entry<K, V> {
        K key;
        V value;
        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }
        public K getKey() {
            return key;
        }
        public void setKey(K key) {
            this.key = key;
        }
        public V getValue() {
            return value;
        }
        public void setValue(V value) {
            this.value = value;
        }
        @Override
        public String toString() {
            return "Entry{" +
                    "key=" + key +
                    ", value=" + value +
                    '}';
        }
    }
}

package MyDataStructures.散列;

import java.util.LinkedList;
import java.util.Set;

/**
 * 采用LinkList来实现自己的HashMap
 *
 * @param <K>
 * @param <V>
 */
public class MyHashMap<K, V> implements MyMap<K, V> {
    private static int DEFAULT_INITIAL_CAPACITY = 4;  //默认初始容量
    private static int MAXIMUM_CAPACITY = 1 << 30; // 最大容量 2^30
    private int capacity; //容量
    private static float DEFAULT_MAX_LOAD_FACTOR = 0.75f; //加载因子
    private float loadFactorThreshold; //自定义的加载因子
    private int size = 0; //元素个数
    LinkedList<MyMap.Entry<K, V>>[] table; //链表数组 链表存储的对象是Entry对象 Entry是MyMap中的内部类 封装了key和value

    public MyHashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_LOAD_FACTOR); // this(4,0.75) 默认值
    }

    public MyHashMap(int initialCapacity) { // 传入容量
        this(initialCapacity, DEFAULT_MAX_LOAD_FACTOR);
    }

    public MyHashMap(int initialCapacity, float loadFactorThreshold) { // 传入容量和加载因子
        if (initialCapacity > MAXIMUM_CAPACITY) {
            this.capacity = MAXIMUM_CAPACITY;
        } else {
            this.capacity = trimToPowerOf2(initialCapacity);
        }
        this.loadFactorThreshold = loadFactorThreshold;
        table = new LinkedList[capacity];
    }

    private int trimToPowerOf2(int initialCapacity) {  // 返回的是一个2的幂 大于传入的初始值 比如传入7,则返回值为8 2的三次幂
        int capacity = 1;
        while (capacity < initialCapacity) {
            capacity <<= 1;
        }
        return capacity;
    }

    private void removeEntries() {  //删除所有的Entry对象
        for (int i = 0; i < capacity; i++) {
            if (table[i] != null) {
                table[i].clear(); //调用的是LinkedList的clear()方法
            }
        }
    }

    @Override
    public void clear() { // 散列表清除
        size = 0;  //元素大小值归零
        removeEntries(); //元素删除
    }

    @Override
    public boolean containsKey(K key) { //查找是否包含key
        if (get(key) != null)
            return true;
        else
            return false;
    }

    @Override
    public boolean containsValue(V value) { //查找是否包含value
        for (int i = 0; i < capacity; i++) {
            if (table[i] != null) { // 数组中的条目不为空
                LinkedList<Entry<K, V>> bucket = table[i]; //得到条目对象 即保存了Entry对象的链表
                for (Entry<K, V> entry : bucket) { //遍历
                    if (entry.getValue().equals(value))
                        return true;
                }
            }
        }
        return false;
    }

    @Override
    public Set<Entry<K, V>> entrySet() { //得到存储了Entry对象的Set集合
        java.util.Set<MyMap.Entry<K, V>> set = new java.util.HashSet<>();
        for (int i = 0; i < capacity; i++) {
            if (table[i] != null) { //数组条目不为空
                LinkedList<Entry<K, V>> bucket = table[i]; //找到为链表的条目
                for (Entry<K, V> entry : bucket)
                    set.add(entry);
            }
        }
        return set;
    }

    @Override
    public V get(K key) { //通过key值在散列表中查找Value
        int bucketIndex = hash(key.hashCode()); //通过散列函数得到条目在数组中的索引
        if (table[bucketIndex] != null) { //条目不为空
            LinkedList<Entry<K, V>> bucket = table[bucketIndex]; //找到条目
            for (Entry<K, V> entry : bucket) { //遍历条目中的对象
                if (entry.getKey().equals(key)) // 查询key值是否相等
                    return entry.getValue(); //相等返回Value
            }
        }
        return null;
    }

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

    @Override
    public Set<K> keySet() { //返回包含了Key值的Set集合
        java.util.Set<K> set = new java.util.HashSet<>();
        for (int i = 0; i < capacity; i++) { // 遍历每个条目
            if (table[i] != null) {
                LinkedList<Entry<K, V>> bucket = table[i];  //得到条目
                for (Entry<K, V> entry : bucket) { //遍历每个条目
                    set.add(entry.getKey()); //添加key值到set集合
                }
            }
        }
        return set;
    }

    @Override
    public V put(K key, V value) {
        if (get(key) != null) { // 当key在map中
            int bucketIndex = hash(key.hashCode()); //通过散列函数求出key在table[]的索引值
            LinkedList<Entry<K, V>> entries = table[bucketIndex]; // 得到条目对象
            for (Entry<K, V> entry : entries) {//遍历条目中对象
                if (entry.getKey().equals(key)) { //如果key值相同 把新值存入 返回旧值
                    V oldValue = entry.getValue();
                    entry.value = value;
                    return oldValue;
                }
            }
            if (size >= capacity * loadFactorThreshold) { // 判断当前元素个数 大于 容量*加载因子时 去扩容
                if (capacity == MAXIMUM_CAPACITY)
                    throw new RuntimeException("Exceeding maximum capacity");
                rehash();
            }
        }
        int bucketIndex = hash(key.hashCode()); // 得到索引值
        if (table[bucketIndex] == null) { //如果此时这个条目没用一个对象的话 就创建一个对象
            table[bucketIndex] = new LinkedList<Entry<K, V>>();
        }
        table[bucketIndex].addLast(new MyMap.Entry<K, V>(key, value)); //把Entry这个对象存入到链表的末尾
        size++;
        return value;
    }

    @Override
    public void remove(K key) { //通过Key删除
        int bucketIndex = hash(key.hashCode()); //得到条目索引值
        if (table[bucketIndex] != null) {
            LinkedList<Entry<K, V>> bucket = table[bucketIndex]; //得到条目
            for (Entry<K, V> entry : bucket) { //遍历条目
                if (entry.getKey().equals(key)) { //查询是否key值相等
                    bucket.remove(entry); //删除entry对象
                    size--;
                    break;
                }
            }
        }
    }

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

    @Override
    public Set<V> vlaues() { //返回了包含了value值的Set集合
        java.util.Set<V> set = new java.util.HashSet<>();
        for (int i = 0; i < capacity; i++) { //遍历数组
            if (table[i] != null) {
                LinkedList<Entry<K, V>> bucket = table[i]; //得到条目
                for (Entry<K, V> entry : bucket) { //遍历条目中的Entry对象
                    set.add(entry.getValue());//添加到集合
                }
            }
        }
        return set;
    }

    private int hash(int hashCode) { //散列函数
        return supplementalHash(hashCode) & (capacity - 1);
    }

    private static int supplementalHash(int h) { //
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    private void rehash() {//先把散列表的容量变成两倍,然后把所有条目在重新放入到新的散列表中
        java.util.Set<Entry<K, V>> set = entrySet(); //得到包含Entry对象的Set集合
        capacity <<= 1; //容量变成两倍
        table = new LinkedList[capacity];
        size = 0;
        for (Entry<K, V> entry : set) {
            put(entry.getKey(), entry.getValue()); //重新放入到新的散列表中
        }
    }

    @Override
    public String toString() {
        StringBuilder result = new StringBuilder("[");
        for (int i = 0; i < capacity; i++) {
            if (table[i] != null && table[i].size() > 0) {
                for (Entry<K, V> entry : table[i])
                    result.append(entry);
            }
        }
        result.append("]");
        return result.toString();
    }
}

解释在代码中 图片为HashMap的数据结构存储图