前注:本文介绍的HashMap并非Java类库的实现。而是根据哈希表知识的一个实现。

上文介绍了开放地址法实现HashTable,它的缺点是对hashCode映射为地址后如果出现重复地址,则会占用其他元素的位置。这样HashTable存储容量有限,而且不便于算法理解。本文介绍链地址法实现HashMap。

链地址法内部仍然有一个数组,但区别与开放地址法,该数组存储的是一个链表的引用。当根据hashCode计算出数组下表后,对元素的增删查改都是在该数组元素所指向的链表上完成的。这就解决了hashCode重复的问题。因为,当hashCode重复,多个元素对应同一个地址,但元素实际存储的位置在数组对应的链表上。所以相同hashCode的不同元素可以存储在同一位置。

下面是代码实现:

package org.lyk.interfaces;

public interface IMap<K,V>
{
/**
* 根据key值增加一个value,如果key重复,则新元素替换旧元素
* @param key
* @param value
*/
public void put(K key, V value);
/**
* 根据key值移除value
* @param key
* @return
*/
public boolean remove(K key);
public V get(K key);
public boolean contains(K key);
public void replace(K key, V value); }

IMap

package org.lyk.impl;

import java.util.ArrayList;
import org.lyk.interfaces.IMap; public class HashMap<K,V> implements IMap<K, V>
{
private class KeyValue
{
private K key;
private V value; public KeyValue(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;
} }
private int maxSize = 10;
private Object[] table; public HashMap()
{
this.table = new Object[this.maxSize];
for(int i = 0; i < this.maxSize; i++)
{
this.table[i] = new java.util.ArrayList<KeyValue>();
}
} @Override
public void put(K key, V value)
{
int index = this.getIndex(key);
KeyValue kv = this.find(key);
if(kv == null)
{
((java.util.List<KeyValue>)this.table[index]).add(new KeyValue(key, value));
}
else
{
kv.setValue(value);
}
} @Override
public boolean remove(K key)
{
int index = this.getIndex(key);
java.util.List<KeyValue> kvs = (java.util.List<KeyValue>)this.table[index];
int listIndex = -1;
for(KeyValue kv : kvs)
{
if(kv.key.equals(key))
{
listIndex = kvs.indexOf(kv);
}
}
if(listIndex != -1)
{
kvs.remove(listIndex);
return true;
}
return false;
} @Override
public V get(K key)
{
KeyValue kv= this.find(key);
if(kv != null)
return kv.getValue();
else
return null;
} @Override
public boolean contains(K key)
{
if(this.get(key) != null)
return true;
else
return false;
} @Override
public void replace(K key, V value)
{
KeyValue kv = this.find(key);
if(kv != null)
{
kv.setValue(value); }
} private int getIndex(K key)
{
return Math.abs(key.hashCode())%this.maxSize;
} private KeyValue find(K key)
{
int index = this.getIndex(key);
java.util.List<KeyValue> kvs = (java.util.List<KeyValue>)this.table[index];
for(KeyValue kv : kvs)
{
if(kv.key.equals(key))
{
return kv;
}
} return null;
}
}

HashMap

链地址法实现HashMap的更多相关文章

  1. java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测).链地址法.再哈希.建立公共溢出区 标签: hashmaphashmap冲突解决冲突的方法冲突 2016-0 ...

  2. POJ 3007 Organize Your Train part II(哈希链地址法)

    http://poj.org/problem?id=3007 题意 :给你一个字符串,让你无论从什么地方分割,把这个字符串分成两部分s1和s2,然后再求出s3和s4,让你进行组合,看能出来多少种不同的 ...

  3. C# Dictionary源码剖析---哈希处理冲突的方法有:开放定址法、再哈希法、链地址法、建立一个公共溢出区等

    C# Dictionary源码剖析 参考:https://blog.csdn.net/exiaojiu/article/details/51252515 http://www.cnblogs.com/ ...

  4. PKU 2002 Squares(二维点哈希+平方求余法+链地址法)

    题目大意:原题链接 给定平面上的N个点,求出这些点一共可以构成多少个正方形. 解题思路: 若正方形为ABCD,A坐标为(x1, y1),B坐标为(x2, y2),则很容易可以推出C和D的坐标.对于特定 ...

  5. SWUST OJ 1012哈希表(链地址法处理冲突)

    哈希表(链地址法处理冲突) 1000(ms) 10000(kb) 2676 / 6911 采用除留余数法(H(key)=key %n)建立长度为n的哈希表,处理冲突用链地址法.建立链表的时候采用尾插法 ...

  6. Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...

  7. 链地址法查找成功与不成功的平均查找长度ASL

    晚上,好像是深夜了,突然写到这类题时遇到的疑惑,恰恰这个真题只让计算成功的ASL,但我想学一下不成功的计算,只能自己来解决了,翻了李春葆和严蔚敏的教材没有找到相关链地址法的计算,于是大致翻到两篇不错的 ...

  8. poj3349(哈希+链地址法)

    给出N个六边形的6个边长,问其中是否有完全相同的两个六边形,完全相同包括边的长度和位置都要相同.边给出的顺序是逆时针或者顺时针的. 给每个6边形一个哈希值,方法是对6条边长度的平方和取模 #inclu ...

  9. 哈希查找解决地址冲突的两种最常见方法(线性探测再散列,链地址法)C++实现

    #include<iostream>#include<iomanip>using namespace std; typedef struct Node{ int data; s ...

随机推荐

  1. 练习使用XRecyclerView,可上拉下拉刷新。

    package com.lixu.testxrecyclerview; import android.support.v7.app.AppCompatActivity; import android. ...

  2. SAP Adapter启动报错

    在启动Adapter的时候,抛出GateWay Service Exception 当时用的gateway service是“sapgw00” 解决方法:这是由于当sap系统向本机注册服务的时候出错, ...

  3. 实验一《开发环境的熟悉》&实验二《固件设计》

    20145312&20145338 实验一<开发环境的熟悉>&实验二<固件设计> 合作博客链接:http://www.cnblogs.com/yx2014531 ...

  4. 简单通过java的socket&serversocket以及多线程技术实现多客户端的数据的传输,并将数据写入hbase中

    业务需求说明,由于公司数据中心处于刚开始部署的阶段,这需要涉及其它部分将数据全部汇总到数据中心,这实现的方式是同上传json文件,通过采用socket&serversocket实现传输. 其中 ...

  5. 简单介绍Javascript匿名函数和面向对象编程

    忙里偷闲,简单介绍一下Javascript中匿名函数和闭包函数以及面向对象编程.首先简单介绍一下Javascript中的密名函数. 在Javascript中函数有以下3中定义方式: 1.最常用的定义方 ...

  6. ARM compiler No such file or directory

    /********************************************************************************* * ARM compiler No ...

  7. firefox 不识别background-position-y / background-position-x

    火狐不识别background-position-y 或background-position-x; 案例: 页面: 背景图: 一列按钮,点击时让当前背景图的background-position-y ...

  8. xmind的第七天笔记

  9. linux与windows的不同

    linux 严格区分大小写:linux 所有内容都以文件形式保存,包括用户和硬件:linux 不以文件后缀名来区分文件类型:但有一些便于管理员区分文件类型的约定俗称的后缀:windows下的程序不能直 ...

  10. poj3180 强连通

    题意:给定一张 n 点 m 边的有向图,问有多少个强连通分量点数大于等于2 . 题意看懂基本就没有问题了. #include<stdio.h> #include<string.h&g ...