Java散列和散列码的实现

Posted 小甜瓜安东泥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java散列和散列码的实现相关的知识,希望对你有一定的参考价值。

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



以上是关于Java散列和散列码的实现的主要内容,如果未能解决你的问题,请参考以下文章

Java集合:散列与散列码

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

Java 集合和映射表

初识java集合——散列表(HashTable)

Guava 10-散列

Java集合—散列与散列码