码迷,mamicode.com
首页 > 其他好文 > 详细

由浅入深解析HashMap---HashMap简单实现 增、删、查。

时间:2016-04-20 23:35:30      阅读:344      评论:0      收藏:0      [点我收藏+]

标签:

    如果让我们自己来设计HashMap,应该怎么做呢?数组。用数组存储节点,每个节点有key和value信息。那首先我们得要有节点存储key,value。

节点设计

在这个Node类中,有三个属性,hash值、key、value值。

技术分享
 1 class Node<K,V> {
 2         final int hash; //hash值
 3         final K key;//key
 4         V value;//value
 5 //构造函数
 6         Node(int hash, K key, V value, Node<K,V> next) {
 7             this.hash = hash;
 8             this.key = key;
 9             this.value = value;
10             this.next = next;
11         }
12 
13         public final K getKey()        { return key; }
14         public final V getValue()      { return value; }
15         public final String toString() { return key + "=" + value; }
16 
17         public final boolean equals(Object o) {
18            if (o == this)
19              return true;          
20                if (Objects.equals(key, o.getKey()) &&
21                    Objects.equals(value, o.getValue()))
22                    return true;
23 
24             return false;
25         }
26 }
View Code

注意:这里的构造函数中多了个next,大家忽略即可。奇怪,添加了这个代码块,怎么编辑的时候删除不了。哎。。。

初始化数组

定义一个容量为100的数组,用来存储node节点。 DEFAULT_INITIAL_CAPACITY ,它必须是必须是2的幂,在JDK提供的HashMap它的值为1 << 4,也就是16,这里直接填16不可以吗?为啥一定要这样写?

技术分享
1  static final int DEFAULT_INITIAL_CAPACITY=100;
2  transient Node<K,V>[] table;
3     /**
4      * 构造函数
5      */
6     public SimpleHashMap()
7   {
8       table=(Node<K,V>[])new Node[DEFAULT_INITIAL_CAPACITY];
9   }
View Code

增加操作-put

对一个容量为100的数组中添加元素其实很简单,具体步骤如下:

1)对key值进行hash,获取hash值。

2)通过上面获取的hash值、key、value值,创建node节点。

3)通过hash值和数组长度获取对应的下标。

4)对获取的下标赋值。

注意:这里对key进行hash调用的hash函数,具体我也不明白为啥要这样设计?

技术分享
1 static final int hash(Object key) {
2       int h;
3       return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
4   }
View Code

另外,根据hash值和容量(数组长度)获取对应的下标,具体我也不明白为啥要这样设计?

技术分享
1 i = (n - 1) & hash
View Code

 具体的put代码如下:

技术分享
 1  public V put(K key, V value)
 2     {
 3         //创建新节点
 4         Node<K,V> p; int n, i;
 5         //获取长度
 6         n=table.length;
 7         //对key值进行hash
 8         int hash=hash(key);
 9         //目前没有考虑hash冲突
10         table[i = (n - 1) & hash]=newNode(hash,key,value);
11         //返回原来的值
12         return value;
13         
14     }
15 //创建新节点
16  Node<K,V> newNode(int hash, K key, V value) {
17       return new Node<>(hash, key, value);
18   }
View Code

删除操作-remove

删除操作其实和添加差不多,首先要获取下标,然后再将下标的值赋值为null。

技术分享
 1   public V remove(Object key) {
 2         Node<K,V> e;
 3         return (e = removeNode(hash(key), key)) == null ?
 4             null : e.value;        
 5     }
 6     /**
 7      * 删除节点。
 8      * 目前不考虑冲突,当对应的下标有值且不为null时,返回该值,并将对应的值设置为Null
 9      * 这里考虑不太完善,因为hashmap是允许value为null的,这样并没有真正删除这个元素。
10      * @param hash
11      * @param key
12      * @return
13      */
14     final Node<K,V> removeNode(int hash, Object key) {
15         Node<K,V> p;int index;
16         p=table[index = (table.length - 1) & hash];
17         if(p!=null)
18         {
19             table[index]=null;
20         }
21         return p;
22     }
View Code

查询操作-get

和remove、put操作一样,也是需要根据key值获取下标,然后再返回对应的value值。

技术分享
 1  /**
 2      * 根据key值,获取value值
 3      * @param key
 4      * @return
 5      */
 6     public V get(Object key) {
 7         Node<K,V> e;
 8         return (e = getNode(hash(key), key)) == null ? null : e.value;
 9         
10     }
11     /**
12      * 获取对应的值
13      * @param hash
14      * @param key
15      * @return
16      */
17     final Node<K,V> getNode(int hash, Object key) {
18        return  table[(table.length - 1) & hash];
19     }
View Code

是否存在该元素--containskey

根据key值判断是否存在该元素,其实和get操作一样,只是这里返回的是布尔值。

技术分享
1  /**
2      * 是否存在对于的key值
3      * @param key
4      * @return
5      */
6     public boolean containsKey(Object key) {
7         return getNode(hash(key), key) != null;
8         
9     }
View Code

 

哇!是不是很简单呢?这里有两个疑问,就是不知道那个下标的获取和hash值得获取为啥要那样设计?是因为这样是最优的吗?下标的获取这种方法,发生冲突的几率就少很多吗?在整个系列中,我并没有讨论HashMap继承AbstractMap,实现Map接口。

 

由浅入深解析HashMap---HashMap简单实现 增、删、查。

标签:

原文地址:http://www.cnblogs.com/icbcfang/p/5414795.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!