20162325 金立清 S2 W11 C20
20162325 2017-2018-2 《程序设计与数据结构》第11周学习总结
教材关键概念摘要
在哈希方法中,元素保存在哈希表中,其在表中的位置由哈希函数确定。
两个元素或关键字映射到表中同一个位置的情形,称为冲突。
将每个元素映射到表中唯一位置的哈希函数称为理想哈希函数。
抽取仅适用元素值或关键字中的一部分来计算保存元素的位置。
在移位折叠方法中,将关键字的各部分加在一起计算下标。
将字符串中各字符按二进制格式进行处理,长度依赖方法和平方取中方法也适用于字符串。
虽然Java为所有的对象提供了hashcode方法,最好还是为特定的类定义一个具体的哈希函数。
处理冲突的链式方法,将哈希表看成是集合的表而不是各独立单元的表。
处理冲突的开放地址方法,即在表中寻找不同于该元素 初次哈希到的另一个开放的位置。
装载因子是哈希表扩展之前,表中允许的最大占有百分比。
哈希方法
HashCode是返回对象的哈希码。跟HashMap和Hashtable没多大关系。
HashTable是方法是同步的,HashMap不是。
HashMap中可以存在一条key或value为空的记录,Hashtable不可以。
HashTable继承自Dictionary,HashMap继承自Map接口。
HashCode
在Java中,哈希码代表对象的特征。
例如对象 String str1 = “aa”, str1.hashCode= 3104
String str2 = “bb”, str2.hashCode= 3106
String str3 = “aa”, str3.hashCode= 3104
根据HashCode由此可得出str1!=str2,str1==str3
哈希码产生的依据:哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。
下面给出几个常用的哈希码的算法。
1:Object类的hashCode.返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。
2:String类的hashCode.根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串内容相同,返回的哈希码也相同。
3:Integer类,返回的哈希码就是Integer对象里所包含的那个整数的数值,例如Integer i1=new Integer(100),i1.hashCode的值就是100 。由此可见,2个一样大小的Integer对象,返回的哈希码也一样。
类 HashMap<K,V>
java.lang.Object
java.util.AbstractMap<K,V>
java.util.HashMap<K,V>
类型参数:
K - 此映射所维护的键的类型
V - 所映射值的类型
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashCode和HashMap之间的关系
import java.util.HashMap;
public class Test {
//重写Equals不重写HashCode
static class Key {
private Integer id;
private String value;
public Key(Integer id, String value) {
super();
this.id = id;
this.value = value;
}
@Override
public boolean equals(Object o) {
if(o == null || !(o instanceof Key)) {
return false;
}else {
return this.id.equals(((Key)o).id);
}
}
}
//重写Equals也重写HashCode
static class Key_ {
private Integer id;
private String value;
public Key_(Integer id, String value) {
super();
this.id = id;
this.value = value;
}
@Override
public boolean equals(Object o) {
if(o == null || !(o instanceof Key_)) {
return false;
}else {
return this.id.equals(((Key_)o).id);
}
}
@Override
public int hashCode() {
return id.hashCode();
}
}
public static void main(String[] args) {
//test hashcode
HashMap<Object, String> values = new HashMap<Object, String>(5);
Test.Key key1 = new Test.Key(1, "one");
Test.Key key2 = new Test.Key(1, "one");
System.out.println(key1.equals(key2));
values.put(key1, "value 1");
System.out.println(values.get(key2));
Test.Key_ key_1 = new Test.Key_(1, "one");
Test.Key_ key_2 = new Test.Key_(1, "one");
System.out.println(key_1.equals(key_2));
System.out.println(key_1 == key_2);
values.put(key_1, "value 1");
System.out.println(values.get(key_2));
}
}
由上述例子可见:
只重写了equasl方法的Key类 在用做Hash中的键值的时候 两个equasl为true的对象不能获取相应 的Value的
而重写了hashCode方法和equals方法的key_类 两个相等的对象 可以获取同一个Value的,这样更符合生活中 的逻辑
HashMap对象是根据Key的hashCode来获取对应的Vlaue 因而两个HashCode相同的对象可以获取同一个Value
哈希函数
- 实际中的Hash函数是指把一个大范围映射到一个小范围。把大范围映射到一个小范围的目的往往是为了节省空间,使得数据容易保存。除此以外,Hash函数往往应用于查找上。所以,在考虑使用Hash函数之前,需要明白它的几个限制:
- Hash的主要原理就是把大范围映射到小范围;所以,你输入的实际值的个数必须和小范围相当或者比它更小。不然冲突就会很多。
- 由于Hash逼近单向函数;所以,你可以用它来对数据进行加密。
- 不同的应用对Hash函数有着不同的要求;比如,用于加密的Hash函数主要考虑它和单项函数的差距,而用于查找的Hash函数主要考虑它映射到小范围的冲突率。
- Hash函数应用的主要对象是数组(比如,字符串),而其目标一般是一个int类型。以下我们都按照这种方式来说明。
一般的说,Hash函数可以简单的划分为如下几类:
- 加法Hash;
- 位运算Hash;
- 乘法Hash;
- 除法Hash;
- 查表Hash;
- 混合Hash;
解决冲突
常用的解决hash冲突的方法
开放地址法
拉链法(链地址法)
多重散列法(再哈希法)
公共溢出区法
具体参见【java基础 10】hash算法冲突解决方法 - CSDN博客
从哈希表中删除元素
List
public class Demo {
public static void main(String[] args) {
List<Object> obj = new ArrayList<Object>();
obj.add("a");
obj.add("b");
obj.add("c");
System.out.println("移除前:" + obj.toString());
Iterator<Object> it = obj.iterator();
for(int i=0; i<obj.size(); i++){
System.out.println(i);
Object name = it.next();
if("a".equals(name) || "b".equals(name)){
it.remove();
i--;
}
}
System.out.println("移除后: " + obj.toString());
}
Set
public class Demo {
public static void main(String[] args) {
Set<Object> obj = new HashSet<Object>();
obj.add("a");
obj.add("b");
obj.add("c");
System.out.println("移除前:" + obj.toString());
Iterator<Object> it = obj.iterator();
for(int i=0; i<obj.size(); i++){
System.out.println(i);
Object name = it.next();
if("a".equals(name) || "b".equals(name)){
it.remove();
i--;
}
}
System.out.println("移除后: " + obj.toString());
}
API中的哈希表
- 比较常用的有
Hashtable、HashMap、HashSet、HashCode
教材学习中的问题和解决过程
- 问题1:课堂测试题

问题1解决方案:参考博客教你轻松计算AOE网关键路径(转)
问题2:HashTable和HashMap区别
问题2解决方案:
有七点不同
第一,继承的父类不同。
第二,线程安全性不同。
第三,是否提供contains方法第四,key和value是否允许null值。
第五,两个遍历方式的内部实现上不同。
第六,hash值不同。
第七,内部实现使用的数组初始化和扩容方式不同。
代码调试中的问题和解决过程
问题1:JDK中有些方法、类被划了横杠
解答:

代码托管

上周考试错题总结
- 活动尚未结束
本周结对学习情况
- 20162311
- 结对学习内容
- 如何画AOE网,求关键路径
其他(感悟、思考等,可选)
- 这周的班级活动和口语考试占用了部分时间,再加上还有团队任务,时间上就很紧张,又是熬夜才完成的博客……然而明天还有当天截止的实验四,感觉有点吃不消。
学习进度条
| 代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
|---|---|---|---|---|
| 目标 | 5000行 | 30篇 | 400小时 | |
| 第一周 | 58/ | 1/1 | 10/10 | |
| 第二周 | 8/18 | |||
| 第三周 | 134/ | 3/4 | 12/ 30 | |
| 第四周 | 2/6 | 12/42 | ||
| 第五&六周 | 750/ 6595 | 5/11 | 24/66 | |
| 第七周 | 764/7068 | 7/13 | 18/84 | |
| 第八周 | 888/7956 | 9/15 | 20/104 | |
| 第九周 | 475/8431 | 12/18 | 22/126 | |
| 第十周 | 1429/9860 | 16/22 | 24/150 | |
| 第十一周 | 977/10837 | 19/25 | 48/198 |
计划学习时间: 23小时
实际学习时间: 24小时
改进情况:多思考,多总结
参考资料
- 最简单的哈希表删除元素 - CSDN博客
- 应用Hash函数(java描述) - CSDN博客
- 浅析Java中Map与HashMap,Hashtable,HashSet的区别_java_脚本之家
- Java中hashCode()方法以及HashMap()中hash()方法
- HashMap/HashSet,hashCode,哈希表 - 晋心 - 博客园
- HashCode和hashMap hashTable - CSDN博客
20162325 金立清 S2 W11 C20的更多相关文章
- 20162325 金立清 S2 W9 C18
20162325 2017-2018-2 <程序设计与数据结构>第9周学习总结 教材学习内容概要 堆是一棵完全二叉树,其中每个元素大于等于其所有子结点的值. 向堆中添加一个元素的方法是,首 ...
- 20162325 金立清 S2 W7 C16
20162325 2017-2018-2 <程序设计与数据结构>第7周学习总结 教材学习内容概要 树是非线性结构,其元素组织为一个层次结构 树的度表示树种任意结点的最大子结点数 有m个元素 ...
- 20162325 金立清 S2 W5 C14
20162325 2017-2018-2 <程序设计与数据结构>第5周学习总结 关键内容摘要 集合是收集并组织其他对象的对象 集合中的元素一般由加入集合的次序或元素之间某些固有的关系而组织 ...
- 20162325 金立清 S2 W3 C13
20162325 2017-2018-2 <程序设计与数据结构>第3周学习总结 教材学习内容概要 查找是在一组项内找到指定目标或是确定目标不存在的过程 高效的查找使得比较的次数最少 Com ...
- 20162325 金立清 S2 W10 C19
20162325 2017-2018-2 <程序设计与数据结构>第10周学习总结 认识 线性表和树两类数据结构,线性表中的元素是"一对一"的关系,树中的元素是" ...
- 20162325 金立清 S2 W6 C15
20162325 2017-2018-2 <程序设计与数据结构>第6周学习总结 教材学习内容概要 队列是先进先出(FIFO)的集合 队列是保存重复编码k值的一种有效结构 实现模拟时常用队列 ...
- 20162325 金立清 S2 W8 C17
20162325 2017-2018-2 <程序设计与数据结构>第8周学习总结 教材学习内容概要 二叉查找树是一棵二叉树,对于其中的每个结点,左子树上的元素小于父结点的值,而右子树上的元素 ...
- 20162325金立清 实验四 Android程序设计 实验报告
实验四 Android程序设计 实验报告 代码托管地址 码云链接 实验内容 安装使用Android Stuidio Activity测试 UI测试 布局测试 事件处理测试 Android程序设计-1 ...
- 2017-2018 第一学期201623班《程序设计与数据结构》-第9&10周作业问题总结
一.作业内容 第8周作业 http://www.cnblogs.com/rocedu/p/7484252.html#WEEK08 第9周作业 http://www.cnblogs.com/rocedu ...
随机推荐
- [转]Laplace算子和Laplacian矩阵
1 Laplace算子的物理意义 Laplace算子的定义为梯度的散度. 在Cartesian坐标系下也可表示为: 或者,它是Hessian矩阵的迹: 以热传导方程为例,因为热流与温度的梯度成正比,那 ...
- os._exit(), sys.exit(), exit()
1. sys.exit(n) 退出程序引发SystemExit异常, 可以捕获异常执行些清理工作. n默认值为0, 表示正常退出. 其他都是非正常退出. 还可以sys.exit("sorry ...
- 彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian...)[转]
最近有一些朋友常问我一些乱码的问题,和他们交流过程中,发现这个编码的相关知识还真是杂乱不堪,不少人对一些知识理解似乎也有些偏差,网上百度, google的内容,也有不少以讹传讹,根本就是错误的(例如说 ...
- Ubuntu_安装Wiz笔记
前言 安装完成了Linux,有了搜狗输入法,我们还需要笔记软件,本文主要介绍如何安装为知笔记 安装步骤 找到wiz官网:http://www.wiz.cn/ 获取Linux安装教程 安装QT 下载的Q ...
- Python的set集合详解
Python 还包含了一个数据类型 -- set (集合).集合是一个无序不重复元素的集.基本功能包括关系测试和消除重复元素.集合对象还支持 union(联合),intersection(交),dif ...
- Matlab读取txt中用空格分隔的数据文件到矩阵
转载...哪儿 忘记了 由于要做的项目中涉及到数据处理,初涉及到matlab.今天需要把一组只用空格分开的数据读取到一个三维矩阵,然后对这个矩阵进行处理. 思路是:首先用importdata读入txt ...
- python中的多进程
具体参考这个博客地址:http://www.cnblogs.com/lxmhhy/p/6052167.html
- ObjectInputStream与ObjectOutputStream
雇员类 package io; import java.io.Serializable; @SuppressWarnings("serial") public class Emp ...
- CVE-2012-4969
Microsoft Internet Explorer ‘CMshtmlEd::Exec’函数释放后使用漏洞(CNNVD-201209-394) Microsoft Internet Explorer ...
- C语言:1孩半问题
题目: 一孩半,又称独女户二胎,即中国大陆部分农村的一项计划生育政策,第一胎是女孩的夫妻可以生育第二个子女.如果第二胎有n%人工性别选择干预(选择男孩),试问男女比例为多少.(10分)题目内容: 一孩 ...