zoukankan      html  css  js  c++  java
  • java 散列与散列码探讨 ,简单HashMap实现散列映射表运行各种操作示列

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

    package org.rui.collection2.maps;
    /**
     * 散列与散列码
     * 将土拔鼠对象与预报对象联系起来,
     * @author lenovo
     *
     */
    //土拨鼠
    public class Groundhog {
    	protected int number;
    	public Groundhog(int n)
    	{
    		number=n;
    	}
    	@Override
    	public String toString() {
    		return "Groundhog #" + number;
    	}
    }
    

    package org.rui.collection2.maps;
    
    import java.util.Random;
    
    //预測
    public class Prediction {
    	private static Random rand=new Random(47);
    	private boolean shadow=rand.nextDouble()>0.5;
    	
    	@Override
    	public String toString() {
    		if(shadow)
    			return "六周后是冬天";//六个周的冬天six more weeks of winter
    		else
    			return "早春";//早春Early spring!
    	}
    }
    

    package org.rui.collection2.maps;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.util.HashMap;
    import java.util.Map;
    /**
     * 散列与散列码
     * 将土拔鼠对象与预报对象联系起来。
     * 每一个Groundhog被 予一个标识 数字。于是能够在hasmmap中这样查找Prediction:
     * 给我与Groundhog #3相关的prediction
     * prediction类包括一个boolean 和toString 
     * 布尔 值用random来初始化;而Tostring方法则解释结果。

    * detecSpring方法使用反射机制来实例化例用Groundhog类或不论什么从GroundHog派生出来的类. * * @author lenovo * */ public class SpringDetector { //发现 public static <T extends Groundhog> void detectSpring(Class<T> type) throws Exception { Constructor<T> ghog=type.getConstructor(int.class); Map<Groundhog, Prediction> map=new HashMap<Groundhog, Prediction>(); //初始化map for(int i=0;i<10;i++) { map.put(ghog.newInstance(i), new Prediction()); } System.out.println("map:="+map); //生成一个number=3的士拔鼠 Groundhog gh=ghog.newInstance(3); //查找预測 System.out.println("looking up prediction for:"+gh); //在初始化中的map中查找 if(map.containsKey(gh)) System.out.println(map.get(gh)); else System.out.println("key not found "+gh); //看起来非常easy,可是他不工作,无法找到 须要实现hacode 和equals 下章解说 } public static void main(String[] args) throws Exception { detectSpring(Groundhog.class); } } /**output: map:={Groundhog #5=早春, Groundhog #7=早春, Groundhog #8=六周后是冬天, Groundhog #0=六周后是冬天, Groundhog #9=六周后是冬天, Groundhog #2=早春, Groundhog #1=六周后是冬天, Groundhog #4=六周后是冬天, Groundhog #3=早春, Groundhog #6=早春} looking up prediction for:Groundhog #3 key not found Groundhog #3 */


    package org.rui.collection2.maps;
    /**
     * 假设要使用自已的类作为HashMap的健,必须同一时候重载hashCode和equlas
     * 示列
     * @author lenovo
     *
     */
    //土拨鼠2
    public class Groundhog2 extends Groundhog{
    	//public int number;
    	public Groundhog2(int n){ super(n);	}
    	@Override
    	public int hashCode() {
    		return number;
    	}
    	@Override
    	public boolean equals(Object obj) {
    	 return obj instanceof Groundhog2 && 
    			 (number==((Groundhog2)obj).number);
    	}
    
    	
    
    }
    

    package org.rui.collection2.maps;
    /**
     * Groundhog2.hashCode返回Groundhog的标识数字(编号)作为散列码。

    * 在此例中,程序猿负责确保不同的groundhog具有不同的编号。hashCode并不须要总是可以返回唯一的标识 码 * 但equals必须严格推断对象是否同样 * @author lenovo * */ public class SpringDetector2 { public static void main(String[] args) throws Exception { SpringDetector.detectSpring(Groundhog2.class); } } /** map:={Groundhog #0=六周后是冬天, Groundhog #1=六周后是冬天, Groundhog #2=早春, Groundhog #3=早春, Groundhog #4=六周后是冬天, Groundhog #5=早春, Groundhog #6=早春, Groundhog #7=早春, Groundhog #8=六周后是冬天, Groundhog #9=六周后是冬天} looking up prediction for:Groundhog #3 早春 */


    package org.rui.collection2.maps;
    
    import java.util.*;
    
    /**
     * 理解hashCode 
     * 使用散列的目地在于 :你要使用一个对象来查找还有一个对象.
     *  只是使用TreeMap或者你自已实现的Map也能够达到此目地 以下的演示样例用
     * 一对ArrayList实现了一个Map
     * 
     * @author lenovo
     * 
     */
    public class SlowMap<K, V> extends AbstractMap<K, V> {
    	private List<K> keys = new ArrayList<K>();
    	private List<V> values = new ArrayList<V>();
    
    	public V put(K key, V value) {
    		V oldValue = get(key);
    		if (!keys.contains(key)) {
    			keys.add(key);
    			values.add(value);// 加入新的
    		} else
    			// 它将被用来查找表示它在keys列表中的位置的数值型索引 而且这个数字被用作索引来产生与values列表相关联的值
    			values.set(keys.indexOf(key), value);
    		return oldValue;
    	}
    
    	public V get(Object key) {
    		if (!keys.contains(key))
    			return null;
    		return values.get(keys.indexOf(key));
    	}
    
    	public Set<Map.Entry<K, V>> entrySet() {
    		Set<Map.Entry<K, V>> set = new HashSet<Map.Entry<K, V>>();
    		Iterator<K> ki = keys.iterator();
    		Iterator<V> vi = values.iterator();
    		while (ki.hasNext()) {
    			set.add(new MapEntry<K, V>(ki.next(), vi.next()));
    
    		}
    		return set;
    	}
    
    	public static void main(String[] args) {
    		// 慢的
    		SlowMap<String, String> map = new SlowMap<String, String>();
    		map.put("CAMEROON", "yaounde");
    		map.put("A", "aa");
    		map.put("B", "bb");
    		map.put("C", "cc");
    		System.out.println(map);
    		System.out.println(map.get("A"));
    		System.out.println(map.entrySet());
    	}
    
    }
    /**output:
    {CAMEROON=yaounde, C=cc, B=bb, A=aa}
    aa
    [CAMEROON=yaounde, C=cc, B=bb, A=aa]
     */
    

    package org.rui.collection2.maps;
    
    import java.util.Map;
    
    /**
     * 想要创建自已的map类型,就必须同一时候定义Map.Entry的实现
     * 
     * @author lenovo
     * 
     */
    public class MapEntry<K, V> implements Map.Entry<K, V> {
    
    	private K key;
    	private V value;
    
    	public MapEntry(K key, V value) {
    		this.key = key;
    		this.value = value;
    	}
    
    	@Override
    	public K getKey() {
    		return key;
    	}
    
    	@Override
    	public V getValue() {
    		return value;
    	}
    
    	@Override
    	public V setValue(V v) {
    		V result = value;
    		value = v;
    		return result;
    	}
    
    	public int hashCode() {
    		// 异或 不同为1 同样的为0
    		return (key == null ? 0 : key.hashCode())
    				^ (value == null ? 0 : value.hashCode());
    	}
    
    	public boolean equals(Object o) {
    		if (!(o instanceof MapEntry))return false;
    		MapEntry me = (MapEntry) o;
    		return (key == null ?

    me.getKey() == null : key.equals(me.getKey())) && (value == null ? me.getValue() == null : value.equals(me .getValue())); } public String toString() { return key + "=" + value; } }


    package org.rui.collection2.maps;
    
    import java.util.AbstractMap;
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.ListIterator;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * 为速度而散列
     * 
     * 散列的价值在于速度。解决方式之中的一个就是保持健的排序状态。然后使用Collections.binarySearch()查询
     * 数组并不保存健本身。而是通过健对象生成一个数字,将其作为数组的下标。这个数字就是散列码。
     * 注意:这个 实现并不意味着对性能进行了调化,它仅仅是想要展示散列映射表运行的各种操作,
     * @author lenovo
     *
     */
    public class SimpleHashMap<K,V> extends AbstractMap<K, V> {
    
    	
    	static final int SIZE=997;
    	//你不可能拥有一个物理geerics数组
    	//you can't have a physical array of geerics
    	//but you can upcast to one 可是你能够向上抛
    	LinkedList<MapEntry<K,V>>[] buckets=new LinkedList[SIZE];//bucket桶  位
    	/***
    	 * 对于put方法 hasCode将针对健而被调用。而且其结果被强制转换为正数。

    * 为了使产生的数字适合bucket数组的大小 取模操作符将依照该数组的尺寸取模, * 假设数组的某个位置是null,这表示还没有元素被散列至此。所以,为了保存刚散列到该定位的对象 * 须要创建一个新的LinkedList * */ public V put(K key,V value) { V oldValue=null; int index=Math.abs(key.hashCode())%SIZE; if(buckets[index]==null) { buckets[index]=new LinkedList<MapEntry<K,V>>(); } LinkedList<MapEntry<K, V>> bucket=buckets[index]; MapEntry<K,V> pair=new MapEntry<K,V>(key,value); boolean found=false; ListIterator<MapEntry<K,V>> it=bucket.listIterator(); while(it.hasNext()) { MapEntry<K,V> itM=it.next(); if(itM.getKey().equals(key)) { oldValue=itM.getValue(); it.set(itM);//replace old with new found=true; break; } } if(!found) { buckets[index].add(pair); } return oldValue; } /** * get 依照put同样的方式计算在buckets数组中的索引, * 这个非常重要,由于这样能够保证两个方法能够计算同样的位置 */ @Override public V get(Object key) { int index=Math.abs(key.hashCode())%SIZE; if(buckets[index]==null)return null; for(MapEntry<K,V> ipair:buckets[index]) if(ipair.getKey().equals(key)) return ipair.getValue(); return null; } @Override public Set<java.util.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> mpair:bucket) set.add(mpair); } return set; } //////////////////////////////////////////////////////// public static void main(String[] args) { SimpleHashMap<String,String> simple=new SimpleHashMap<String,String>(); simple.put("CAMEROON", "yaounde"); simple.put("A", "aa"); simple.put("B", "bb"); simple.put("C", "cc"); System.out.println(simple); System.out.println(simple.get("B")); System.out.println(simple.entrySet()); } } /***output: {CAMEROON=yaounde, C=cc, B=bb, A=aa} bb [CAMEROON=yaounde, C=cc, B=bb, A=aa] */




  • 相关阅读:
    解决上传文件大小限制 PHP+Apache
    PHP中ftp的连接与操作
    python 批量修改文件名
    pytorch 断点续训练
    图片的读取
    tensor 类型转换
    卷积网络提取图像特征
    U盘拷贝数据到服务器
    1*1卷积核的作用
    skimage
  • 原文地址:https://www.cnblogs.com/yfceshi/p/6741764.html
Copyright © 2011-2022 走看看