zoukankan      html  css  js  c++  java
  • 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>  
  • 相关阅读:
    指针与数组的区别 —— 《C语言深度剖析》读书心得
    console ouput 与 重定向输出 效率对比
    First day in 阿里
    TestNG 使用入门教程
    Spring简单使用简介
    玩转Spring JUnit+mockito+powermock单元测试(使用详解)
    Spring Boot Junit 单元测试详解
    spring @Value注入map、List、Bean、static变量方式及详细使用
    单元测试Junit使用详解
    Mockito & PowerMock详解
  • 原文地址:https://www.cnblogs.com/YuyuanNo1/p/8882423.html
Copyright © 2011-2022 走看看