热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

java散列与散列码探讨,简单HashMap实现散列映射表执行各种操作示列packageorg.rui.collection2.maps;***散列与散列码*将土拔鼠对象与预报对象联系

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 void detectSpring(Class type) throws Exception
{
Constructor ghog=type.getConstructor(int.class);
Map map=new HashMap();

//初始化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 extends AbstractMap {
private List keys = new ArrayList();
private List values = new ArrayList();

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> entrySet() {
Set> set = new HashSet>();
Iterator ki = keys.iterator();
Iterator vi = values.iterator();
while (ki.hasNext()) {
set.add(new MapEntry(ki.next(), vi.next()));

}
return set;
}

public static void main(String[] args) {
// 慢的
SlowMap map = new SlowMap();
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 implements Map.Entry {

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 extends AbstractMap {


static final int SIZE=997;
//你不可能拥有一个物理geerics数组
//you can't have a physical array of geerics
//but you can upcast to one 但是你可以向上抛
LinkedList>[] 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>();
}
LinkedList> bucket=buckets[index];
MapEntry pair=new MapEntry(key,value);
boolean found=false;
ListIterator> it=bucket.listIterator();
while(it.hasNext())
{
MapEntry 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 ipair:buckets[index])
if(ipair.getKey().equals(key))
return ipair.getValue();
return null;
}

@Override
public Set> entrySet() {
Set> set=new HashSet>();
for(LinkedList> bucket:buckets)
{
if(bucket==null)continue;
for(MapEntry mpair:bucket)
set.add(mpair);
}
return set;
}
////////////////////////////////////////////////////////
public static void main(String[] args) {
SimpleHashMap simple=new SimpleHashMap();
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]
*/




推荐阅读
  • Scala 实现 UTF-8 编码属性文件读取与克隆
    本文介绍如何使用 Scala 以 UTF-8 编码方式读取属性文件,并实现属性文件的克隆功能。通过这种方式,可以确保配置文件在多线程环境下的一致性和高效性。 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • Java 中 Writer flush()方法,示例 ... [详细]
  • 本文介绍了如何使用 Spring Boot DevTools 实现应用程序在开发过程中自动重启。这一特性显著提高了开发效率,特别是在集成开发环境(IDE)中工作时,能够提供快速的反馈循环。默认情况下,DevTools 会监控类路径上的文件变化,并根据需要触发应用重启。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
author-avatar
流年时光云
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有