转自:https://blog.csdn.net/al_assad/article/details/52989525

散列和散列码
 
※正确的equals方法应该满足的的条件:
①自反性:x.equals(x) 一定返回true;
②对称性:y.euqlas(x)为true,那么x.equals(y)一定为true;
③传递性:x.equals(y)为true,y.euqlas(z)为true,则z.equals(x)为true;
④一致性:如果x,y中用于等价比较的信息没有变化,那么无论调用y.euqlas(x)多少次,结果都是一致的;
⑤对任何不是null的x,x.equals(null)一定为false;
 
1、在查询方式里,线性查询是最慢的查询方式;
2、散列的价值在于速度,它使用一组数组(Java中储存查询速度最快的数据结构)来储存键的信息(并非键本身);
     数组本身不保存键本身,而是通过键本身生成一个编码,将其作为数组下标,该编码就是散列码,由键的hashCode(散列函数)产生;
     数组保存的一个记录键的list,当在一个数组中的散列码发生冲突时,有外部链接解决冲突,并加入同一个list中;
3、在散列结构里查找一个键:
     ①计算该键的散列码,使用该散列码查询数组;
     ②对该数组下标的list使用根据equals进行线性查询;
4、散列表中的一些术语:
     ①容量:表中的桶buckets位数;
     ②初始容量:表在创建时拥有的桶位数,HashMap和HashSet都允许指定初始容量的构造器;
     ③尺寸:表中当前储存的位数;
     ④负载因子:尺寸/容量,空表负载为0,满表负载为1.0,负载轻产生的冲突可能性小,有利于插入和查询,但是会减慢使用迭代器遍历元素,默认的负载因子为0.75;
     ⑤再散列:当负载达到负载因子的水平时,容器会自动增加容量(双倍增加);
5、散列容器的模型:
 
6、hashCode的实现:
 
 
7、HashMap的实现和key元素实现散列码

  1. <span style="color:#000000;">import java.util.*;
  2. public class SimpleHashMap<K,V> extends AbstractMap<K,V>{
  3. static final int SIZE = 997;  //默认bucket数量;
  4. @SuppressWarnings("unchecked")
  5. LinkedList<MapEntry<K,V>>[] buckets = new LinkedList[SIZE];
  6. //放置映射关系,返回原先的映射Value;
  7. public V put (K key, V value){
  8. int index = Math.abs(key.hashCode()) % SIZE;
  9. if(buckets[index] == null)
  10. buckets[index] = new LinkedList<MapEntry<K, V>>();
  11. V oldValue = null;
  12. LinkedList<MapEntry<K,V>> bucket = buckets[index];
  13. MapEntry<K, V> pair = new MapEntry<K,V>(key,value);
  14. ListIterator<MapEntry<K,V>> iter = bucket.listIterator();
  15. //检查重复key,更新value
  16. boolean found = false;
  17. while(iter.hasNext()){
  18. MapEntry<K,V> tempPair = iter.next();
  19. if(tempPair.getKey().equals(key)){
  20. oldValue = tempPair.getValue();
  21. iter.set(pair);
  22. found = true;
  23. break;
  24. }
  25. }
  26. if(!found)
  27. buckets[index].add(pair);
  28. return oldValue;
  29. }
  30. public V get(Object key){
  31. int index = Math.abs(key.hashCode()) % SIZE;
  32. if(buckets[index] == null)
  33. return null;
  34. for(MapEntry<K,V> pair : buckets[index]){
  35. if(pair.getKey().equals(key))
  36. return pair.getValue();
  37. }
  38. return null;
  39. }
  40. @Override
  41. public Set<Map.Entry<K, V>> entrySet() {
  42. Set<Map.Entry<K, V>> set = new HashSet<Map.Entry<K,V>>();
  43. for(LinkedList<MapEntry<K,V>> bucket : buckets){
  44. if(bucket == null)
  45. continue;
  46. for(MapEntry<K,V> pair : bucket)
  47. set.add(pair);
  48. }
  49. return set;
  50. }
  51. class MapEntry<K,V> implements Map.Entry<K, V>{
  52. K key;
  53. V value;
  54. public MapEntry(K key,V value){
  55. this.key = key;
  56. this.value = value;
  57. }
  58. @Override
  59. public K getKey(){
  60. return  this.key;
  61. }
  62. @Override
  63. public V getValue() {
  64. return this.value;
  65. }
  66. @Override
  67. public V setValue(V value) {
  68. return this.value = value;
  69. }
  70. }
  71. /*实现可以引用在在HashMap对象的key对象,该对象必须实现hashCode方法*/
  72. import java.util.*;
  73. public class CountString {
  74. private static List<String> created = new ArrayList<String>();
  75. //用于记录一次程序运行创建的所哟 String s实例,当s发生重复时,生成唯一的id,以产生唯一的散列值;
  76. private String s ;        //用于记录内容的数据域
  77. private int id = 0;             //记录相同String的CountString对象的编号
  78. public CountString(String str){
  79. this.s = str;
  80. created.add(s);
  81. for(String e : created){
  82. if(e.equals(s))
  83. this.id++;
  84. }
  85. }
  86. public int hashCode(){
  87. int result = 17;                //设置初始偏移量
  88. result = 37*result + s.hashCode();            //37稀释值
  89. result = 37*result + id;               //进行第二次稀释,放置ID值破坏s.hasCode;
  90. return result;
  91. }
  92. public boolean equals(Object o){
  93. return o instanceof CountString && s.equals(((CountString)o).getS())
  94. && id == ((CountString)o).getId();
  95. }
  96. public String getS(){
  97. return this.s;
  98. }
  99. public int getId(){
  100. return  this.getId();
  101. }
  102. public String toString(){
  103. return "String:"+s+" id:"+id+" hashCode: "+hashCode();
  104. }
  105. }
  106. </span>

Java散列和散列码的实现的更多相关文章

  1. 【Java集合学习】HashMap源码之“拉链法”散列冲突的解决

    1.HashMap的概念 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射. HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io ...

  2. java 散列与散列码探讨 ,简单HashMap实现散列映射表运行各种操作示列

    java 散列与散列码探讨 ,简单HashMap实现散列映射表运行各种操作示列 package org.rui.collection2.maps; /** * 散列与散列码 * 将土拔鼠对象与预报对象 ...

  3. [转]java.sql.SQLException: 无效的列索引

    原文地址:http://blog.sina.com.cn/s/blog_6bc811e401011a17.html java.sql.SQLException: 无效的列索引 “无效的列索引”其实是个 ...

  4. java.sql.SQLException: 无效的列索引

    java.sql.SQLException: 无效的列索引 "无效的列索引"其实是个低级的错误,原因无非几个: 1.sql串的?号数目和提供的变量数目不一致: 例如:jdbcTem ...

  5. Java.sql.SQLException: 无效的列类型: 1111

    org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: ...

  6. Cause: java.sql.SQLException: 无效的列索引

    今天调试代码发现“Cause: java.sql.SQLException: 无效的列索引”,查资料得出结论如下: 1.sql串的?号用''括了起来. 例如:select* from user t  ...

  7. oracle: jdbcTypeForNull configuration property. Cause: java.sql.SQLException: 无效的列类型: 1111

    https://www.cnblogs.com/mmlw/p/5808072.html org.mybatis.spring.MyBatisSystemException: nested except ...

  8. Java JTable列顺序和列宽度保存在用户本地

    上周碰到了一个棘手的需求,就是要把用JTable的列顺序和列宽度保存下来,这次用户调整了列宽度,关闭程序,下次再打开时,这个列的宽还是要保持,因为SWing的特性,都是在程序启动时就确定了列顺序和列宽 ...

  9. java学习-zxing生成二维码矩阵的简单例子

    这个例子需要使用google的开源项目zxing的核心jar包 core-3.2.0.jar 可以百度搜索下载jar文件,也可使用maven添加依赖 <dependency> <gr ...

随机推荐

  1. Solr4.0使用

    http://blog.sina.com.cn/s/blog_64dab14801013k7g.html Solr简介 Solr是一个非常流行的,高性能的开源企业级搜索引擎平台,属于Apache Lu ...

  2. WPF SL 属性生成器

    在开发WPF 和SL应用的时候通用会用到MVVM模式,每次写到类属性的时候要不断的写属性更新时通知方法,写多了就嫌烦,就手写了个属性生成工具,在属性更新的时候添加了更新通知方法. 工具中支持自定义类对 ...

  3. 数据库对m³等特殊符号的支持

    目前我只遇到过m³这个特殊符号,会影响正常使用. 比如,我在数据库中搜索: select * from table where container='10m³'; 即使数据库中对应的值,但也无法搜索出 ...

  4. unity3d一个物体围绕另一个物体旋转

    可以使用RotateAround,代码如下: transform.RotateAround (Sun.transform.position, Vector3.down, ); 其中第一个参数是要围绕哪 ...

  5. jquery的onclick(this)方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. android studio - 提取局部变量,全局变量,方法快捷键

    提取局部变量:Ctrl+Alt+V 提取全局变量:Ctrl+Alt+F 提取方法:Shit+Alt+M

  7. Ehcache2 的配置(不使用配置文件)

    EhCache是一个开放源码的,基于标准的高速缓存系统. 网上关于EhCache的使用配置很多,但是一般是基于配置文件的.但是实际应用中.我们可能需要动态的管理缓存,这时候单纯配置文件就不够用了. 所 ...

  8. 解决linux下/etc/rc.local开机器不执行的原因

    前不久因项目需要写了开机启动其他程序的shell脚本,因工作忙,调试完给了技术支持人员,也没去注意过. 到后来,有几台服务器突然被重启了,这时候领导问,怎么开机启动的脚本没起作用,还被批了一顿,哎,做 ...

  9. linux下出现ping:unknown host www.baidu.com问题时的解决办法——ubuntu下局域网络的配置

    如果ping域名的时候出现ping:unknown host  xxx.xxx 但是ping IP地址的时候可以通的话 可知是dns服务器没有配置好, 查看一下配置文件/etc/resolv.conf ...

  10. bzoj2005 能量采集 莫比乌斯或者普通容斥

    /** 题目:bzoj2005 能量采集 链接:https://vjudge.net/contest/178455#problem/F 题意:栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可 ...