java——哈希表 HashTable
在一个类中重写hashCode()和equals()
package Date_pacage.hash; public class Student {
private int grade;
private int cls;
String firstName;
String lastName; Student(int grade, int cls, String firstName, String lastName){
this.grade = grade;
this.cls = cls;
this.firstName = firstName;
this.lastName = lastName;
} //如果没有覆盖这个方法,java会自动给Student这个类的每个对象分配一个hashCode,
//这个自动分配的hashCode是根据对象的地址来分配的
@Override
public int hashCode() { int B = 31; int hash = 0;
hash = hash * B + grade;
hash = hash * B + cls;
//字符串不区分大小写
hash = hash * B + firstName.hashCode();
hash = hash * B + lastName.hashCode(); return hash;
} @Override
public boolean equals(Object o) {
if(this == o) {
return true;
}
if(o == null) {
return false;
}
if(getClass() != o.getClass()) {
return false;
}
Student another = (Student)o;
return this.grade == another.grade &&
this.cls == another.cls &&
this.firstName.toLowerCase().equals(another.firstName.toLowerCase()) &&
this.lastName.toLowerCase().equals(another.lastName.toLowerCase()); }
}
实现一个HashTable:
package Date_pacage.hash; import java.util.TreeMap; //哈希冲突的处理:链地址法
//哈希表的动态空间处理:平均每个地址承载的元素过多一定程度,即扩容
// N/M >= upperTol
//平均每个地址承载的元素过少一定程度,即缩容
//N/M <= lowerTol
public class HashTable<K, V> { private static final int upperTol = 10;
private static final int lowerTol = 2;
private static final int initCapacity = 7;
//这里要求K extends Comparable
private TreeMap<K, V> hashtable[];
//TreeMap[]:这里表达的是一个存储TreeMap类型的数组!
private int M;//hashTable中有M个位置
private int size;//整个哈希表中元素的个数,就是N public HashTable(int M) {
this.M = M;
size = 0;
//哈希表的底层用了TreeMap,那么hashMap是怎么实现的
//Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;
//它支持线程的同步,即任一时刻只有一个线程能写Hashtable,然而,这也导致了Hashtable在写入时会比较慢。
hashtable = new TreeMap[M];
for(int i = 0 ; i < M ; i ++) {
hashtable[i] = new TreeMap<>();
}
} public HashTable() {
this(initCapacity);
} private int hash(K key) {
return (key.hashCode() & 0x7fffffff) % M;
} public int getSize() {
return size;
} public void add(K key, V value) {
//如果有两个字符串的哈希值相同,他们就被分配到一个TreeMap中去
//在将数据传入TreeMap时使用(key, value),
//key是字符串,value是字符串出现的个数
TreeMap<K, V> map = hashtable[hash(key)];
if(map.containsKey(key)) {
map.put(key, value);
}else {
map.put(key, value);
size ++;
if(size >= upperTol * M) {
resize(2 * M);
}
}
} public V remove(K key) {
TreeMap<K, V> map = hashtable[hash(key)];
V ret = null;
if(map.containsKey(key)) {
ret = map.remove(key);
size --;
if(size < lowerTol * M && M / 2 >= initCapacity) {
resize(M / 2);
}
}
return ret;
} public void set(K key, V value) {
TreeMap<K, V> map = hashtable[hash(key)];
if(!map.containsKey(key)) {
throw new IllegalArgumentException(key + "doesn't exist!");
}
map.put(key, value);
} public boolean contains(K key) {
return hashtable[hash(key)].containsKey(key);
} public V get(K key) {
return hashtable[hash(key)].get(key);
} private void resize(int newM) {
TreeMap<K, V>[] newHashTable = new TreeMap[newM];
for(int i = 0 ; i < newM ; i ++) {
newHashTable[i] = new TreeMap<>();
} int oldM = M;
this.M = newM;
for(int i = 0 ; i < oldM ; i ++) {
TreeMap<K, V> map = hashtable[i];
for(K key : map.keySet()) {
newHashTable[hash(key)].put(key, map.get(key));
}
}
this.hashtable = newHashTable;
}
}
hashMap中的hash方法:
作用:是返回输入对象在hashMap数组中的下标值
具体做法:
原始想法是根据hashcode()得到的散列值^数组长度,得到所在数组下标值,缺点是碰撞严重,只用到了散列值中数组长度的低位信息。
优化想法:增加一个扰动函数,也就是
(var1 = var0.hashCode()) ^ var1 >>> 16
相当于是增加了返回值的信息量,扰动之后的值^数组长度,这时得到的数组下标值碰撞次数减少了很多
java——哈希表 HashTable的更多相关文章
- Java中哈希表(Hashtable)是如何实现的
Java中哈希表(Hashtable)是如何实现的 Hashtable中有一个内部类Entry,用来保存单元数据,我们用来构建哈希表的每一个数据是Entry的一个实例.假设我们保存下面一组数据,第一列 ...
- 哈希表(hashtable)的javascript简单实现
javascript中没有像c#,java那样的哈希表(hashtable)的实现.在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的 ...
- Java哈希表入门
Java哈希表(Hash Table) 最近做题经常用到哈希表来进行快速查询,遂记录Java是如何实现哈希表的.这里只简单讲一下利用Map和HashMap实现哈希表. 首先,什么是Map和HashMa ...
- 使用java实现希表的基础功能
用java代码完成哈希表数据结构的简单实现, 以公司雇员的添加修改作为模拟实例 具体代码如下: package com.seizedays.hashtable; import java.util.Sc ...
- 哈希表(Hashtable)简述
一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对,其中 ...
- c/c++ 哈希表 hashtable
c/c++ 哈希表 hashtable 概念:用key去查找value 实现hash函数有很多方法,本文用除留余数法. 除留余数法的概念: 取一个固定的基数的余数,注意不能用偶数,用偶数的话,分布会不 ...
- C#中哈希表(HashTable)的用法详解以及和Dictionary比较
1. 哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对, ...
- 转 C#中哈希表(HashTable)的用法详解
看了一遍有关哈希表的文字,作者总结的真是不错 .收藏起来 1. 哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提 ...
- 哈希表hashTable的Java设计
1:哈希表的概念 2:设计原理 3:哈希表的Java设计
随机推荐
- apt-get默认下载路径
备忘: Ubuntu中apt-get下载的安装包都在哪里呢? 在/var/cache/apt/archives里,里边的安装包可以取出来以备后用.
- 3.3PCL已有点类型介绍和增加自定义的点类型
1.PCL中有哪些可用的PointT类型 这些point类型都位于point_types.hpp文件中,如果用户需要自己定义类型,需要对已有类型了解. 1)PointXYZ---成员变量:float ...
- Entity Framework Tutorial Basics(16):Linq-to-Entities Projection Queries
Linq-to-Entities Projection Queries: Here, you will learn how to write LINQ-to-Entities queries and ...
- PHP 查看扩展信息的命令
PHP 查看扩展信息的命令 这里以查看 Swoole 扩展信息为例. root@639ca1f15214:~# php --ri swoole // php --ri [扩展名称] swoole sw ...
- 巧用 git rebase 将某一部分 commit 复制到另一个分支
一.为什么需要将一个 commit 复制到其他分支上去呢? 在我们的实际开发的过程中,我们的项目中会存在多个分支. 在某些情况下,可能需要将某一个分支上的 commit 复制到另一个分支上去. 二 ...
- CodeForces 402D Upgrading Array (数学+DP)
题意:给出一个数列,可以进行一种操作将某一个前缀除去他们的gcd,有一个函数f(x),f(1) = 0 , f(x) = f(x/p)+1,f(x) = f(x/p)-1(p是坏素数), 求 sum( ...
- [译]Javascript中的switch语句
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- 一键结束port 5037占用
输入cmd进入dos界面,进入android-sdk-windows\platform-tools目录,执行下面命令启动adb start-server出现下面错误* daemon not runni ...
- [CentOS7] 安装sogou输入法
CentOS7 下的默认输入法不是很好用,于是还是用sogou输入法 由于官网只有Ubuntu版本的sogou输入法安装包,于是先下载下来再说,博主用的版本在这里(密:ph13): 接下来解压data ...
- 编译原理-First集和Follow集
刚学first集和follow集的时候,如果上课老师没有讲明白或者自己没听明白,自己看的时候还真是有点难理解,不过结合着具体的题目可以理解的更快. 先看一下两种集合的求法: First集合的求法: ...