HashMap代码实现

package collections;

import java.util.Collection;
import java.util.Set;

//类的范型参数,文件名称没有 范型参数描述。
//开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列) 再哈希法 链地址法 建立一个公共溢出区

public interface MyMap<K, V> {
 boolean isEmpty(); //如果此映射未包含键-值映射关系,则返回 true。
 int size() ;//返回此映射中的键-值映射关系数。
 
 V put(K key, V value); //将指定的值与此映射中的指定键关联(可选操作)。
 void putAll(MyMap<? extends K,? extends V> m) ;//从指定映射中将所有映射关系复制到此映射中(可选操作)。
 
 boolean containsKey(K key) ;   //如果此映射包含指定键的映射关系,则返回 true。
 boolean containsValue(V value);//如果此映射将一个或多个键映射到指定值,则返回 true。
 
 //三种集合视图  和单个值对象
 V get(K key); //返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
 Set<K> keySet();        //返回此映射中包含的键的 Set 视图。
 Collection<V> values(); //返回此映射中包含的值的 Collection 视图。
 Set<MyMapEntry<K,V>> entrySet() ;//返回此映射中包含的映射关系的 Set 视图。
 
 
 V remove(K key); //如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
 void clear();      //从此映射中移除所有映射关系(可选操作)。
   
    boolean equals(Object o) ;//比较指定的对象与此映射是否相等。
 int hashCode(); //返回此映射的哈希码值。
}

package collections;

import java.io.Serializable;
import java.util.Collection;
import java.util.Set;
// Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。
//所有通用的映射实现类应该提供两个“标准的”构造方法:一个 void(无参数)构造方法,用于创建空映射;
//一个是带有单个 Map 类型参数的构造方法,用于创建一个与其参数具有相同键-值映射关系的新映射。


//HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。//打个比方, 第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0] = A。
//一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?HashMap会这样做:B.next = A,Entry[0] = B,
//如果又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。


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

 private static final long serialVersionUID = 364045005810968434L;
 
 private MyMapEntryImpl[] table;//Entry数组表
    static final int DEFAULT_INITIAL_CAPACITY = 16;//默认数组长度
    private int size;

    // 构造函数
    public MyHashMap() {
        table = new MyMapEntryImpl[DEFAULT_INITIAL_CAPACITY];
        size = DEFAULT_INITIAL_CAPACITY;
    }
 
    MyHashMap(int initialCapacity){};//构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。
    MyHashMap(int initialCapacity, float loadFactor){} //构造一个带指定初始容量和加载因子的空 HashMap。
    MyHashMap(MyHashMap<? extends K,? extends V> m){} //构造一个映射关系与指定 Map 相同的新 HashMap。

   
    //获取数组长度
    public int getSize() {
        return size;
    }
   
    // 求index   列表的 哈希索引位置
    static int indexFor(int h, int length) {
        return h % (length - 1);
    }

    //获取元素
    public V get(K key) {
        if (key == null)
            return null;
        int hash = key.hashCode();// key的哈希值
        int index = indexFor(hash, table.length);// 求key在数组中的下标
       
        for (MyMapEntryImpl<K, V> e = table[index]; e != null; e = e.next) {
            K k = e.key;
            //hashcode 相同 及 equals也相同
            if (e.key.hashCode() == hash && (k == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

    // 添加元素  有的话 返回原来旧的值《
    public V put(K key, V value) {
     //允许null null 键值对
        if (key == null)
            return null;
       
        int hash = key.hashCode();
        int index = indexFor(hash, table.length);

        // 如果添加的key已经存在,那么只需要修改value值即可
        for (MyMapEntryImpl<K, V> e = table[index]; e != null; e = e.next) {
            K k = e.key;
            if (k.hashCode() == hash && (k == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                return oldValue;// 原来的value值
            }
        }
        // 如果key值不存在,那么需要添加
        MyMapEntryImpl<K, V> e = table[index];// 获取当前数组中的e
        table[index] = new MyMapEntryImpl<K, V>(key, value, e);// 新建一个Entry,并将其指向原先的e
        return null;
    }
   
 public void clear() {
  // TODO Auto-generated method stub
 }

 public boolean containsKey(Object key) {
  // TODO Auto-generated method stub
  return false;
 }

 public boolean containsValue(Object value) {
  // TODO Auto-generated method stub
  return false;
 }

 public Set entrySet() {
  // TODO Auto-generated method stub
  return null;
 }


 public boolean isEmpty() {
  // TODO Auto-generated method stub
  return false;
 }

 public Set keySet() {
  // TODO Auto-generated method stub
  return null;
 }

 public void putAll(MyMap m) {
  // TODO Auto-generated method stub
  
 }

 public V remove(K key) {
  // TODO Auto-generated method stub
  return null;
 }

 public int size() {
  // TODO Auto-generated method stub
  return 0;
 }

 public Collection values() {
  // TODO Auto-generated method stub
  return null;
 }
}

package collections;
public interface MyMapEntry<K, V> {
 K getKey() ;//返回与此项对应的键。
 
 V getValue(); //返回与此项对应的值。
 V setValue(V value); 
 
 boolean equals(Object o);//比较指定对象与此项的相等性。
// (e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &&
// (e1.getValue()==null ? e2.getValue()==null : e1.getValue().equals(e2.getValue()))
 
 int hashCode(); //返回此映射项的哈希码值。
// (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
//  (e.getValue()==null ? 0 : e.getValue().hashCode())
}

 

package collections;

/**
 * hashMap  因为不能修改 键值 所以定义为  final
 * @author wangyuehui
 * @param <K>
 * @param <V>
 */
public class MyMapEntryImpl<K, V> implements MyMapEntry<K, V> {
 final K key;
    V value;
    MyMapEntryImpl<K,V> next;//下一个结点
 
    //构造函数
    public MyMapEntryImpl(K k, V v, MyMapEntryImpl<K,V> n) {
        key = k;
        value = v;
        next = n;
    }

    public final K getKey() {
        return key;
    }

    public final V getValue() {
        return value;
    }

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

    @SuppressWarnings("unchecked")
 public final boolean equals(Object o) {
     //首先判断 是不是当前对象
     //编程技巧 instanceof  回车 自动构建代码块
     if (!(o instanceof MyMapEntryImpl))
            return false;
        MyMapEntryImpl<K, V> e = (MyMapEntryImpl<K, V>)o;

        //先判断键,再判断值  《自身对象,和 其他对象的比较》
        K k1 = getKey();
        K k2 = e.getKey();
        //这个时候有  null值 及  null键的逻辑判断
        if (k1 == k2 || (k1 != null && k1.equals(k2))) {
            V v1 = getValue();
            V v2 = e.getValue();
            if (v1 == v2 || (v1 != null && v1.equals(v2)))
                return true;
        }
        return false;
    }

    public final int hashCode() {
     //括号加错了,算法的实现逻辑
        return (key==null   ? 0 : key.hashCode()) ^ (value==null ? 0 : value.hashCode());
    }

    public final String toString() {
        return getKey() + "=" + getValue();
    }

}

 

转载于:https://my.oschina.net/u/1182621/blog/145681

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值