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]
*/

java 散列与散列码探讨 ,简单HashMap实现散列映射表运行各种操作示列的更多相关文章

  1. sqlserver2005仅当使用了列的列表,并且 IDENTITY_INSERT 为 ON 时,才能在表 'SendMealAddress'中为标识列指定显式值。

    ps = con.prepareStatement("insert into SendMealAddress values(null,?,?,?,?)"); 表有一列是自增长的标识 ...

  2. 重读源码,见证HashMap以及它的朋友们的骚操作

    一.Getting Start Again and again,until you master it.早在接触java.util包的时候,我们都会去阅读ArrayList,甚至也会去阅读HashMa ...

  3. 【Java框架型项目从入门到装逼】第九节 - 数据库建表和CRUD操作

    1.新建学生表 这节课我们来把和数据库以及jdbc相关的内容完成,首先,进行数据库建表.数据库呢,我们采用MySQL数据库,我们可以通过navcat之类的管理工具来轻松建表. 首先,我们得建一个数据库 ...

  4. JDK8;HashMap:再散列解决hash冲突 ,源码分析和分析思路

    JDK8中的HashMap相对JDK7中的HashMap做了些优化. 接下来先通过官方的英文注释探究新HashMap的散列怎么实现 先不给源码,因为直接看源码肯定会晕,那么我们先从简单的概念先讲起   ...

  5. JAVA 之 每日一记 之 算法( 给定一个正整数,返回它在 Excel 表中相对应的列名称。 )

    题目: 给定一个正整数,返回它在 Excel 表中相对应的列名称. 例如: 1 -> A 2 -> B 3 -> C ... 26 -> Z 27 -> AA 28 -& ...

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

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955   您好,我正在参加CSDN博文大赛,如果您喜欢我的文章,希望您能帮我投一票 ...

  7. 【java集合框架源码剖析系列】java源码剖析之HashMap

    前言:之所以打算写java集合框架源码剖析系列博客是因为自己反思了一下阿里内推一面的失败(估计没过,因为写此博客已距阿里巴巴一面一个星期),当时面试完之后感觉自己回答的挺好的,而且据面试官最后说的这几 ...

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

    转载出处:http://blog.csdn.net/ns_code/article/details/36034955 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-va ...

  9. Java源码系列2——HashMap

    HashMap 的源码很多也很复杂,本文只是摘取简单常用的部分代码进行分析.能力有限,欢迎指正. HASH 值的计算 前置知识--位运算 按位异或操作符^:1^1=0, 0^0=0, 1^0=0, 值 ...

随机推荐

  1. MYSQL用户操作管理大杂烩

    一.创建用户 命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明:username - 你将创建的用户名, host - 指定该 ...

  2. SecureCRT远程连接Linux服务器及相关配置

    这里的连接采用的是SSH2协议,关于SSH2协议可百度 一.连接不上可能的原因 1)服务器防火墙iptables /etc/init.d/iptables stop 2)SSH服务有问题 3)客户端到 ...

  3. JSPGen4 自学路线图

  4. Bootstrap 3之美03-独立行,文字环绕,图片自适应,隐藏元素

    本篇主要包括: ■  添加独立的一行■  文字环绕■  图片自适应■  隐藏元素 添加独立的一行 在id为body的section和id为main的section之间,添加2张图片. 我们发现,新加的 ...

  5. .NET泛型04,使用Lazy<T>实现延迟加载

    对于一些"大对象"的创建,我们常常希望延迟加载,即在需要的时候再创建对象实例.现在Lazy<T>很好地支持了这一特点.主要包括: 没有Lazy<T>之前 L ...

  6. 03把IL编译成可执行文件

    1.在记事本中编写IL代码如下: .assembly HelloWorld{} .assembly extern mscorlib{}   .method public static void Mai ...

  7. IE中Ext的comboBox跑到页面左上角

    { xtype:'combo', width:100, //id:'exTypeCom', name:'exType', hiddenName:'exType', displayField:'text ...

  8. 打印后台程序服务没有启动,每次打开Powerdesigner都会要我安装打印机

    原因: 不光这个,就是word也需要你有个打印机.随便安一个就可以了.一般系统自带个Microsoft Office Document Image Writer的还报打印机,要是你有这个打印机的话.查 ...

  9. 解决ElasticSearch5.x中@Field注解之IK分词不能用的问题

    一.概述 环境:ElasticSearch版本5.6.3,SpringBoot 2.0.2.RELEASE,索引myIndex 问题描述:使用@Field注解给实体类指定ik分词解析器(ik_smar ...

  10. 张明楷:案件事实认定方法的七点注意 z

    作者|张明楷 来源|<法学杂志> 大体而言,定罪是一个三段论的推理过程.刑法规范是大前提,案件事实是小前提,如果二者相符合,便可以作出相应的判决.具体地说,法官必须把应当判决的.具体的个案 ...