HashMap实现

package base.base;

import java.io.Serializable;
import java.util.*;

/**
 * @author liu
 * Created 2018 - 11 - 08 - TIME
 */
public class MyHashMap<K, V> implements Serializable {

    // 1.HashMap: 众所周知,HashMap是一个key-value键值对集合,每一个键值对抽象为Entry(Node),这个数组就是HashMap的主干。
    // 2.HashMap数据结构: 哈希表(数组 + 链表)。
    // 接下来,我们就以HashMap的常见操作为例,来驱动我们的理解。


    // 默认容量
    static int DEFAULT_INITIAL_CAPACITY = 16;
    // 最大容量
    static final int MAXIMUM_CAPACITY = 1 << 30;
    // 默认加载因子
    static float DEFAULT_LOAD_FACTOR = 0.75f;
    // 当前容器大小
    private int capacity;
    // 存储数据的table
    transient Node<K, V>[] table;
    // HashMap的大小
    transient int size;
    // 当前HashMap的修改次数
    transient int modCount;
    // 加载因子,也可以称为扩容因子
    float loadFactor;
    // HashMap 键集合
    transient Set<K> keySet;
    // HashMap values集合
    transient Collection<V> values;

    public MyHashMap() {
        this(DEFAULT_INITIAL_CAPACITY);
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

    public MyHashMap(int capacity) {
        if (capacity < 0) {
            throw new RuntimeException();
        } else {
            this.table = new Node[capacity];
            this.capacity = capacity;
            this.size = 0;

        }
    }

    // HashMap节点
    static class Node<K, V> {
        int hash = 0;
        K key = null;
        V value;
        Node<K, V> next;

        Node(int hash, K key, V value, Node<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey() {
            return key;
        }

        public final V getValue() {
            return value;
        }

        @Override
        public final String toString() {
            return key + "=" + value;
        }

        @Override
        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        @Override
        public final boolean equals(Object o) {
            if (o == this) {
                return true;
            }
            if (o instanceof Node) {
                Node<?, ?> e = (Node<?, ?>) o;
                if (Objects.equals(key, e.getKey()) &&
                        Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }

    final int hash(K key) {
//        int h;
//        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
//        double tmp = key.hashCode() * (Math.pow(5, 0.5) - 1) / 2;
//        double digit = tmp - Math.floor(tmp);
//        return (int) Math.floor(digit * capacity);

        return key.hashCode() & (capacity - 1);
    }

    public int size() {
        return size;
    }

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

    public V get(K key) {
        Node<K, V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

    private Node<K, V> getNode(int hash, K key) {
        Node<K, V>[] tab = table;
        Node<K, V> p;

        p = tab[hash];

        while (p != null) {
            if (p.getKey().equals(key)) {
                return p;
            }
            p = p.next;
        }

        return null;
    }

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

    private V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        Node<K, V>[] tab = table;
        Node<K, V> p;

        Node<K, V> newNode = new Node<K, V>(hash, key, value, null);
        p = tab[hash];
        while (p != null) {
            if (p.getKey().equals(key)) {
                p.value = value;
                return value;
            }
            p = p.next;
        }

        newNode.next = tab[hash];
        tab[hash] = newNode;

        size++;
        return value;
    }

    public V remove(K key) {
        Node<K, V> e;
        return (e = removeNode(hash(key), key)) == null ?
                null : e.value;
    }

    public boolean containsKey(K key) {
        return getNode(hash(key), key) != null;
    }

    private Node<K, V> removeNode(int hash, K key) {
        Node<K, V>[] tab = table;
        Node<K, V> p = tab[hash];

        // If the node is head node
        if (p.getKey().equals(key)) {
            tab[hash] = p.next;
            size--;
            return p;
        } else {
            while (p.next != null) {
                if (p.next.getKey().equals(key)) {
                    if (p.next.next == null) {
                        p.next = null;
                        size--;
                        return p.next;
                    }
                    p.next = p.next.next;
                    p.next = null;  //GC
                    size--;
                    return p.next;
                }
                p = p.next;
            }
        }
        return null;
    }

    public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }

    abstract class HashIterator {
        Node<K, V> next;
        Node<K, V> current;
        int expectedModCount;
        int index;

        HashIterator() {
            expectedModCount = modCount;
            Node<K, V>[] t = table;
            current = next = null;
            index = 0;
            if (t != null && size > 0 && index < t.length) {
                next = t[index++];
            }
        }

        public final boolean hasNext() {
            return next != null;
        }

        final Node<K, V> nextNode() {
            Node<K, V>[] t;
            Node<K, V> e = next;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            if ((next = (current = e).next) == null && (t = table) != null) {
                do {
                } while (index < t.length && (next = t[index++]) == null);
            }
            return e;
        }

        public final void remove() {
            Node<K, V> p = current;
            if (p == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            current = null;
            K key = p.key;
            removeNode(hash(key), key);
            expectedModCount = modCount;
        }

    }

    final class KeyIterator extends HashIterator implements Iterator<K> {
        public final K next() {
            return nextNode().key;
        }
    }

    final class KeySet<K> extends AbstractSet<K> {
        @Override
        public Iterator<K> iterator() {
            return (Iterator<K>) new KeyIterator();
        }

        public final int size() {
            return size;
        }

    }

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值