在一个类中重写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的更多相关文章

  1. Java中哈希表(Hashtable)是如何实现的

    Java中哈希表(Hashtable)是如何实现的 Hashtable中有一个内部类Entry,用来保存单元数据,我们用来构建哈希表的每一个数据是Entry的一个实例.假设我们保存下面一组数据,第一列 ...

  2. 哈希表(hashtable)的javascript简单实现

    javascript中没有像c#,java那样的哈希表(hashtable)的实现.在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的 ...

  3. Java哈希表入门

    Java哈希表(Hash Table) 最近做题经常用到哈希表来进行快速查询,遂记录Java是如何实现哈希表的.这里只简单讲一下利用Map和HashMap实现哈希表. 首先,什么是Map和HashMa ...

  4. 使用java实现希表的基础功能

    用java代码完成哈希表数据结构的简单实现, 以公司雇员的添加修改作为模拟实例 具体代码如下: package com.seizedays.hashtable; import java.util.Sc ...

  5. 哈希表(Hashtable)简述

    一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对,其中 ...

  6. c/c++ 哈希表 hashtable

    c/c++ 哈希表 hashtable 概念:用key去查找value 实现hash函数有很多方法,本文用除留余数法. 除留余数法的概念: 取一个固定的基数的余数,注意不能用偶数,用偶数的话,分布会不 ...

  7. C#中哈希表(HashTable)的用法详解以及和Dictionary比较

    1.  哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对, ...

  8. 转 C#中哈希表(HashTable)的用法详解

    看了一遍有关哈希表的文字,作者总结的真是不错 .收藏起来 1.  哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提 ...

  9. 哈希表hashTable的Java设计

    1:哈希表的概念 2:设计原理 3:哈希表的Java设计

随机推荐

  1. iOS 添加Empty Application模板

    在Apple最新的XCode6.x中没有了Empty Application模板,好在XCode可以添加模板,而且可以自定义模板. 首先可以到XCode5.x中复制 Empty Application ...

  2. 使用RSS提升DPDK应用的性能(转)

    本文描述了RSS以及在DPDK中如何配置RSS达到性能提升和统一分发. 什么是RSS RSS(Receive Side Scaling)是一种能够在多处理器系统下使接收报文在多个CPU之间高效分发的网 ...

  3. Mind Map-在线软件(转)

     From http://blog.sina.com.cn/s/blog_74b687ac0102dtp1.html 第一款:http://tu.mindpin.com/ 用非常简单, 先用Email ...

  4. 杭电ACM刷题(2):1005,Number Sequence 标签: 杭电acmC语言 2017-05-11 22:43 116人阅读

    Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1 ...

  5. p3634 [APIO2012]守卫

    传送门 分析 1.先预处理出不被0覆盖的点,然后对每个点处理出在它左边离他最近的点和在他右边理他最近的点. 2.对于每个至少存在一个忍者的区间,先将它左右边界处理为不被0所覆盖.排序后将包含其他区间的 ...

  6. SSH框架(三) struts2的登陆示例

    因为最近在学习使用SSH框架(struts2+spring+hibernate),下面来介绍表现层struts2的使用方法. (一)添加struts2的包 见上一篇博客,先看一下添加的各个文件的目录结 ...

  7. 数据结构_Summary

    问题描述 可怜的 Bibi 丢了好几台手机以后,看谁都像是小偷,他已经在小本本上记下了他认为的各个地点的小偷数量.现在我们将 Bibi 的家附近的地形抽象成一棵有根树. 每个地点都是树上的一个节点,节 ...

  8. Comparator 排序

    例1: import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import ja ...

  9. SharpCompress压缩和解压缩,并解决压缩的中文乱码问题

    一.下载SharpCompress库 二.解压缩 (1)不带密码 /// <summary> /// 解压缩(支持rar,zip) /// </summary> /// < ...

  10. org.apache.commons.lang3包中的isEmpty和isBlank

    主要为了区分一下empty和blank的用法,先看源码: isEmpty public static boolean isEmpty(CharSequence cs) { return cs == n ...