Java散列和散列码的实现

散列和散列码

※正确的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元素实现散列码
<span style="color:#000000;">import java.util.*;
public class SimpleHashMap<K,V> extends AbstractMap<K,V>{
       static final int SIZE = 997;  //默认bucket数量;
       @SuppressWarnings("unchecked")
       LinkedList<MapEntry<K,V>>[] buckets = new LinkedList[SIZE];
       
       
       //放置映射关系,返回原先的映射Value;
       public V put (K key, V value){
             int index = Math.abs(key.hashCode()) % SIZE;
             if(buckets[index] == null)
                    buckets[index] = new LinkedList<MapEntry<K, V>>();
             
             V oldValue = null;
             LinkedList<MapEntry<K,V>> bucket = buckets[index];
             MapEntry<K, V> pair = new MapEntry<K,V>(key,value);
             ListIterator<MapEntry<K,V>> iter = bucket.listIterator();
             //检查重复key,更新value
             boolean found = false;
             while(iter.hasNext()){
                    MapEntry<K,V> tempPair = iter.next();
                    if(tempPair.getKey().equals(key)){
                          oldValue = tempPair.getValue();
                          iter.set(pair);
                          found = true;
                          break;

       }
             }
             if(!found)
                    buckets[index].add(pair);
             return oldValue;
       }
       
       public V get(Object key){
             int index = Math.abs(key.hashCode()) % SIZE;
             if(buckets[index] == null)
                    return null;
             for(MapEntry<K,V> pair : buckets[index]){
                    if(pair.getKey().equals(key))
                          return pair.getValue();
             }
             return null;
       }
       @Override
       public Set<Map.Entry<K, V>> entrySet() {
             Set<Map.Entry<K, V>> set = new HashSet<Map.Entry<K,V>>();
             for(LinkedList<MapEntry<K,V>> bucket : buckets){
                    if(bucket == null)
                          continue;
                    for(MapEntry<K,V> pair : bucket)
                          set.add(pair);
             }
             return set;
       } 
       
       class MapEntry<K,V> implements Map.Entry<K, V>{
             K key;
             V value;
             public MapEntry(K key,V value){
                    this.key = key;
                    this.value = value;
             }
             @Override
             public K getKey(){
                    return  this.key;
             }
             @Override
             public V getValue() {
                    return this.value;
             }
             @Override
             public V setValue(V value) {
                    return this.value = value;
             }
             
       }

/*实现可以引用在在HashMap对象的key对象,该对象必须实现hashCode方法*/
import java.util.*;
public class CountString {
       
       private static List<String> created = new ArrayList<String>();  
       //用于记录一次程序运行创建的所哟 String s实例,当s发生重复时,生成唯一的id,以产生唯一的散列值;
       private String s ;        //用于记录内容的数据域
       private int id = 0;             //记录相同String的CountString对象的编号
       public CountString(String str){
             this.s = str;
             created.add(s);
             for(String e : created){
                    if(e.equals(s))
                          this.id++;
             }
       }
       public int hashCode(){
             int result = 17;                //设置初始偏移量
             result = 37*result + s.hashCode();            //37稀释值
             result = 37*result + id;               //进行第二次稀释,放置ID值破坏s.hasCode;
             return result;
       }
       
       public boolean equals(Object o){
             return o instanceof CountString && s.equals(((CountString)o).getS())
                          && id == ((CountString)o).getId();
       }
       
       public String getS(){
             return this.s;
       }
       public int getId(){
             return  this.getId();
       }
       public String toString(){
             return "String:"+s+" id:"+id+" hashCode: "+hashCode();
       }
}
</span>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值