链地址法实现HashMap
前注:本文介绍的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的更多相关文章
- java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测).链地址法.再哈希.建立公共溢出区 标签: hashmaphashmap冲突解决冲突的方法冲突 2016-0 ...
- POJ 3007 Organize Your Train part II(哈希链地址法)
http://poj.org/problem?id=3007 题意 :给你一个字符串,让你无论从什么地方分割,把这个字符串分成两部分s1和s2,然后再求出s3和s4,让你进行组合,看能出来多少种不同的 ...
- C# Dictionary源码剖析---哈希处理冲突的方法有:开放定址法、再哈希法、链地址法、建立一个公共溢出区等
C# Dictionary源码剖析 参考:https://blog.csdn.net/exiaojiu/article/details/51252515 http://www.cnblogs.com/ ...
- PKU 2002 Squares(二维点哈希+平方求余法+链地址法)
题目大意:原题链接 给定平面上的N个点,求出这些点一共可以构成多少个正方形. 解题思路: 若正方形为ABCD,A坐标为(x1, y1),B坐标为(x2, y2),则很容易可以推出C和D的坐标.对于特定 ...
- SWUST OJ 1012哈希表(链地址法处理冲突)
哈希表(链地址法处理冲突) 1000(ms) 10000(kb) 2676 / 6911 采用除留余数法(H(key)=key %n)建立长度为n的哈希表,处理冲突用链地址法.建立链表的时候采用尾插法 ...
- Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...
- 链地址法查找成功与不成功的平均查找长度ASL
晚上,好像是深夜了,突然写到这类题时遇到的疑惑,恰恰这个真题只让计算成功的ASL,但我想学一下不成功的计算,只能自己来解决了,翻了李春葆和严蔚敏的教材没有找到相关链地址法的计算,于是大致翻到两篇不错的 ...
- poj3349(哈希+链地址法)
给出N个六边形的6个边长,问其中是否有完全相同的两个六边形,完全相同包括边的长度和位置都要相同.边给出的顺序是逆时针或者顺时针的. 给每个6边形一个哈希值,方法是对6条边长度的平方和取模 #inclu ...
- 哈希查找解决地址冲突的两种最常见方法(线性探测再散列,链地址法)C++实现
#include<iostream>#include<iomanip>using namespace std; typedef struct Node{ int data; s ...
随机推荐
- easyui 之ComboTree 用法Demo
实现效果如下: HTML部分: <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="ser ...
- SVN - 忽略已经提交的文件
1.在本地删除要忽略的文件 2.与资源库同步,提交删除的文件 3.忽略文件
- C#面向对象学习笔记概要
1.面向对象不是取代面向过程的. 2.面向对象的三个特性:封装.继承.多态. 3.字段.方法.属性(后面讲)都可以叫做类的成员,他们都需要定义访问级别.访问级别的用处在于控制成员在哪些地方可以被访问, ...
- sql 跨域
1. 开通分布式查询权限 reconfigure reconfigure 2. 查询 ',NETACS.dbo.tb_car) a select * from opendatasource('SQLO ...
- JS 功能弹框封装
// 功能提示弹框 function messageBox ( option ) { var html = ''; html += '<div class="message-box-h ...
- Devexpress datagrid动态添加显示指定列的gridView
代码如下: public class DXGridControlHelper { /// <summary> /// 获取显示指定列的GridView /// </summary&g ...
- java中,去除空白的方法
有时候,我们页面传过来的值,或者做excel导入时填入的值都需要去掉像空格一样的一些特殊字符,下面这个方法可去掉像制表符,换行键,回车,空格或者不在ACSII中 的特殊字符 /** * 去除字符串开始 ...
- linux的七种文件类型
d 目录 - 普通文件 l 符号链接 s 套接字文件 b 块设备文件 二进制文件 c 字符设备文件 p 命名管道文件
- ✡ leetcode 164. Maximum Gap 寻找最大相邻数字差 --------- java
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- C语言实现简单线程池(转-Newerth)
有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程池.下面是一个C语言实现的简单的线程池. 头文件: 1: #ifndef THREAD_POOL ...