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);
		//看起来很简单,但是他不工作,无法找到  需要实现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]
 */

java 散列与散列码探讨 ,简单HashMap实现散列映射表执行各种操作示列,布布扣,bubuko.com

时间: 2024-10-05 05:12:46

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

第 2 天 字符串,列表,元组常用方法助记操作示列

以下示列在python3.4中运行! 一.字符串的方法: isalnum ##判断是否是字母或者是数字 1 >>> n = 'welcome' 2 >>> n.isalnum() 3 True 4 >>> isalpha ##判断是否是字母 1 >>> n = 'welcome' 2 >>> n.isalpha() 3 True 4 >>>   isdecimal ##判断是否是十进制小数 >

Netty源码分析第2章(NioEventLoop)----&gt;第6节: 执行selector操作

Netty源码分析第二章: NioEventLoop 第六节: 执行select操作 分析完了selector的创建和优化的过程, 这一小节分析select相关操作 跟到跟到NioEventLoop的run方法: protected void run() { for (;;) { try { switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) { case SelectStrategy.CONTINUE

JSon数据操作示列

序列化数据: public class AccountCallbackData { /// <summary> /// 银行名称 /// </summary> public string BankName { get; set; } /// <summary> /// 开户人 /// </summary> public string Holder { get; set; } /// <summary> /// 银行账号 /// </summ

【Java集合源码剖析】HashMap源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap. HashMap 实现了Serializable接口,因此它支持序列化,

转:【Java集合源码剖析】HashMap源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955   您好,我正在参加CSDN博文大赛,如果您喜欢我的文章,希望您能帮我投一票,谢谢! 投票地址:http://vote.blog.csdn.net/Article/Details?articleid=35568011 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动

【Java集合源码剖析】HashMap源码剖析(转)

HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap. HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆. HashMap源码剖析 HashMap的源码如下(加入了比较详细的注释): [ja

[java源码解析]对HashMap源码的分析(二)

上文我们讲了HashMap那骚骚的逻辑结构,这一篇我们来吹吹它的实现思想,也就是算法层面.有兴趣看下或者回顾上一篇HashMap逻辑层面的,可以看下HashMap源码解析(一).使用了哈希表得"拉链法". 我打算按这个顺序来讲HashMap:几个关键属性 -> 构造方法-> 存取元素方法 ->解决hash冲突方法->HashMap扩容问题. 4个关键属性: /** *HashMap的存储大小 */ transient int size; /** * HashMa

Java线程池ThreadPoolExector的源码分析

前言:线程是我们在学习java过程中非常重要的也是绕不开的一个知识点,它的重要程度可以说是java的核心之一,线程具有不可轻视的作用,对于我们提高程序的运行效率.压榨CPU处理能力.多条线路同时运行等都是强有力的杀手锏工具.线程是如此的重要,那么我们来思考这样一个问题.假设我们有一个高并发,多线程的项目,多条线程在运行的时候,来一个任务我们new一个线程,任务结束了,再把它销毁结束,这样看似没有问题,适合于低并发的场景,可是当我们的项目投入到生产环境,一下涌入千条任务的时候,线程不断的new执行