`
bearsorry
  • 浏览: 94377 次
  • 性别: Icon_minigender_2
  • 来自: 湖南
社区版块
存档分类
最新评论

用java分析hash表结构及性能(二)

 
阅读更多

七,用代码来验证自己写的hash表以及性能分析(之前的rehash方法写错了,现在更正过来了!)

package cn.java1118;
/**
 * 自己写的hashmap类
 * @author acer
 *
 * @param <K>:关键字类
 * @param <V>:数据域类
 */
public class MyHashMap04<K,V> {

	//存放键值对的数组
	private Entry<K,V>[] hashTable;
	//当前容量的大小
	private int numberOfEntries;
	//装载因子
	private static final double MAX_LOAD_FACTOR=0.75;
	//集合初始化的一个大小
	static final int DEFAULT_INITIAL_CAPACITY = 16;
	
	public MyHashMap04(){
		this(DEFAULT_INITIAL_CAPACITY);
	}
	
	public MyHashMap04(int tablesize){
		//实例化数组的大小
		hashTable = new Entry[tablesize];
		//初始化的时候hash表里面什么都木有
		this.numberOfEntries=0;
	}
	/**
	 * 补充哈希函数
	 * @param h:每一个对象都有的hashcode
	 * @return:另一种hashcode
	 */
	static int hash(int h) {
		//直接copyJDK自带的这个算法
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
	
	/**
	 * 根据key取得value值
	 * @param key:键
	 * @return:键所对应的值
	 */
	public V getValue(K key){
		
		//要返回的值
		V result = null;
		//得到要key在数组的下标
		int hash = hash(key.hashCode());
		int index = indexFor(hash, hashTable.length);
		//对键值对链表进行遍历
		for (Entry<K,V> e = hashTable[index]; e != null; e = e.next) {
	            Object k;
	            if (e.hash == hash && ((k = e.key) == key || key.equals(k))){
	                return e.value;
	            }
	        }
		return result;
	}
	/**
	 * 添加元素
	 * @param key
	 * @param value
	 * @return:添加成功则为null,否则返回之前的值
	 */
	public V add(K key,V value){
		//键值为null时的处理方法
		if (key == null)
            return putForNullKey(value);
		//返回值变量
		V oldValue;
		
		//得到这个键在数组中的下标
		int hash = hash(key.hashCode());
		int index = indexFor(hash, hashTable.length);
		//看是否存在一样的键和hashcode
		for (Entry<K,V> e = hashTable[index]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            	//存在这样的键值对了
                oldValue = e.value;
                e.value = value;
               
                return oldValue;
            }
        }
		//插入一个键值对的时候当前的容量会+1
		numberOfEntries++;
		//进行插入
		addEntry(hash, key, value, index);
		return null;
	}
	/**
	 * 当插入的键位null时的处理
	 * @param value:值
	 * @return:插入成功则返回null,不成功则返回这个键原来所对应的值
	 */
	private V putForNullKey(V value) {
        for (Entry<K,V> e = hashTable[0]; e != null; e = e.next) {
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
                return oldValue;
            }
        }
        numberOfEntries++;
        addEntry(0, null, value, 0);
        return null;
    }
	/**
	 * 插入键值对链表
	 * @param hash:hashcode
	 * @param key:键
	 * @param value:值
	 * @param bucketIndex:数组上的下标
	 */
	void addEntry(int hash, K key, V value, int bucketIndex) {
		//将原来的保留
		Entry<K,V> e = hashTable[bucketIndex];
		//在原来的基础上添加
		hashTable[bucketIndex] = new Entry<K,V>(hash, key, value, e);
		if(!isHashTableTooFull()){
			//看是否超出其装载因子
			rehash();
		}
	    }
	
	//检验hash表的装载因子是否大于默认值
	private boolean isHashTableTooFull() {
		//装载因子是有大小限制的
		if(numberOfEntries/hashTable.length>=MAX_LOAD_FACTOR){
			return false;
		}
		return true;
	}

	/**
	 * 再hash的方法
	 */
	private void rehash() {
		//保留原hash表
		Entry<K, V>[] oldHashTable = hashTable;
		int oldSize = hashTable.length;
		//扩大为原来的两倍
		int newSize = oldSize*2;
		hashTable = new Entry[newSize];
		numberOfEntries=0;
		
		//还要遍历原hash表,即将原来放进来的数据重新插入到新的hash表中
		for(int i=0;i<oldHashTable.length;i++){
			Entry<K, V> e = oldHashTable[i];
			if(e!=null){
				do{
					Entry<K, V> next = e.next;
				int index = indexFor(hash(e.hash), newSize);
			addEntry(e.hash, e.key, e.value, index);
			e=next;
				}while(e!=null);
				
			}
		}
	}
	/**
	 * 删除指定key的键值对
	 * @param key:键
	 * @return
	 */
	 public V remove(Object key) {
	        Entry<K,V> e = removeEntryForKey(key);
	        return (e == null ? null : e.value);
	    }
	 /**
	  * 跟查找的过程差不多
	  * @param key
	  * @return
	  */
	 final Entry<K,V> removeEntryForKey(Object key) {
	        int hash = (key == null) ? 0 : hash(key.hashCode());
	        int i = indexFor(hash, hashTable.length);
	        Entry<K,V> prev = hashTable[i];
	        Entry<K,V> e = prev;

	        while (e != null) {
	            Entry<K,V> next = e.next;
	            Object k;
	            if (e.hash == hash &&
	                ((k = e.key) == key || (key != null && key.equals(k)))) {
	                numberOfEntries--;
	                if (prev == e)
	                    hashTable[i] = next;
	                else
	                    prev.next = next;
	                return e;
	            }
	            prev = e;
	            e = next;
	        }

	        return e;
	    }
	 
	/**
	 * 得到在数组中的下标位置
	 * @param h:hashcode
	 * @param length:hash表的长度
	 * @return:下标位置
	 */
	static int indexFor(int h, int length) {
        return h & (length-1);
    }
	/**
	 * 实例化一个装键值对链表
	 * @author acer
	 *
	 * @param <K>
	 * @param <V>
	 */
	private class Entry<K,V>{
		private K key;
		private V value;
		//每一个对象都有一个hashcode,是唯一的,在map中不能存放hashcode一样的对象
		private int hash;
		//下一个键值对节点
		private Entry<K,V> next;
		
		private Entry(int hash,K key,V value,Entry<K,V>next){
			this.key = key;
			this.value = value;
			this.next = next;
			this.hash = hash;
		}

		public K getKey() {
			return key;
		}

		public V getValue() {
			return value;
		}
		//重写equals方法
		 public final boolean equals(Object o) {
	            if (!(o instanceof Entry))
	                return false;
	            Entry e = (Entry)o;
	            //得到两个比较的key值
	            Object k1 = getKey();
	            Object k2 = e.getKey();
	            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
	            	//得到两个比较的value值
	                Object v1 = getValue();
	                Object v2 = e.getValue();
	                if (v1 == v2 || (v1 != null && v1.equals(v2)))
	                    return true;
	            }
	            return false;
	        }
	}
}

 

  

性能分析代码:

package cn.java1118;

import java.util.HashMap;

public class Test1 {  
	  
    public static void main(String[] args) {  
    	//自己的hashmap
    	MyHashMap04<String, String> mm = new MyHashMap04<String, String>();   
        Long aBeginTime=System.currentTimeMillis();  
        for(int i=0;i<1000000;i++){  
        mm.add(""+i, ""+i*100);  
        }  
        Long aEndTime=System.currentTimeMillis();//记录EndTime  
        System.out.println("insert time-->"+(aEndTime-aBeginTime));  
          
        Long lBeginTime=System.currentTimeMillis();//记录BeginTime  
        mm.getValue(""+100000);  
        Long lEndTime=System.currentTimeMillis();//记录EndTime  
        System.out.println("seach time--->"+(lEndTime-lBeginTime));
        
        Long rBeginTime=System.currentTimeMillis();//记录BeginTime  
        mm.remove(""+10000);  
        Long rEndTime=System.currentTimeMillis();//记录EndTime  
        System.out.println("remove time--->"+(rEndTime-rBeginTime));
    	
    	//系统的hashmap
//    	HashMap<String, String> mm = new HashMap<String, String>();   
//        Long aBeginTime=System.currentTimeMillis();//记录BeginTime  
//        for(int i=0;i<1000000;i++){  
//        mm.put(""+i, ""+i*100);  
//        }  
//        Long aEndTime=System.currentTimeMillis();//记录EndTime  
//        System.out.println("insert time-->"+(aEndTime-aBeginTime));  
//          
//        Long lBeginTime=System.currentTimeMillis();//记录BeginTime  
//        mm.get(""+100000);  
//        Long lEndTime=System.currentTimeMillis();//记录EndTime  
//        System.out.println("seach time--->"+(lEndTime-lBeginTime));
//        
//        Long rBeginTime=System.currentTimeMillis();//记录BeginTime  
//        mm.remove(""+10000);  
//        Long rEndTime=System.currentTimeMillis();//记录EndTime  
//        System.out.println("remove time--->"+(rEndTime-rBeginTime));
    }  
}  
 

  

 


 

 

系统的测试结果:

insert time-->2148
seach time--->0

我的测试结果:

insert time-->2236
seach time--->0
remove time--->0

看,查找的速度为0呃,插入也只要2秒多。。。

 

还有一个是存储空间的测试:

 

 

 

 

 

<!--EndFragment-->

分享到:
评论

相关推荐

    哈希计算工具 java-hash.7z

    综上所述,`java-hash.7z` 工具包可能包含用于Java环境下的各种哈希计算工具和示例,帮助开发者进行数据校验、安全存储、性能优化等工作。通过理解和应用这些哈希计算技术,可以提升软件的安全性和效率。

    打造最快的Hash表(和Blizzard的对话)

    通过上述分析,我们可以看到Blizzard的Hash表实现不仅体现了对散列技术的深刻理解,而且还展示了如何利用多个散列值来进一步提高Hash表的性能和准确性。这种技术尤其适用于处理大量数据的情况,能够显著减少冲突的...

    Java里多个Map的性能比较(TreeMap、HashMap、ConcurrentSkipListMap)

    在Java编程中,Map接口是用于存储键值对的数据结构,而Java提供了多种Map的实现,包括TreeMap、HashMap和ConcurrentSkipListMap。本文主要比较了这三种Map的性能,尤其是在插入和查找操作上的效率。 1. **TreeMap**...

    数据结构 课件java版本

    本课件“数据结构 课件java版本”是基于Java编程语言来讲解这一主题的,旨在帮助学生和开发者深入理解数据结构的基本概念,并掌握用Java实现这些数据结构的方法。 在Java中,数据结构主要分为以下几类: 1. **数组...

    哈希表java实现及简单演示

    哈希表,又称为散列表,是一种数据结构,它通过使用散列函数将键(Key)映射到数组的特定位置来实现快速访问。在Java中,哈希表的实现主要依赖于`java.util.HashMap`类,它是基于哈希表的Map接口实现。在这个Java版...

    一致性hashjava实现

    Ketama一致性哈希算法由Last.fm的工程师开发,其设计目标是优化分布式哈希表的性能,特别是在处理大量小键值对时。它通过引入虚拟节点的概念,提高了哈希空间的分布均匀性,减少了因节点变动导致的数据迁移。 1. **...

    10种java性能优化方案.docx

    - **选择高效的算法和数据结构**:例如,使用哈希表而不是链表进行查找操作。 - **避免不必要的计算**:如文档中提到的,优化算法的关键部分,特别是那些占总运行时间较大比例的部分。 - **利用缓存技术**:通过...

    java描述版数据结构(简单易懂)

    哈希表(Hash Table)是一种通过哈希函数快速定位数据的数据结构,实现了键值对的快速查找。Java中的哈希表主要由`java.util.HashMap`和`java.util.Hashtable`类代表,具有O(1)的平均查找时间复杂度。 六、高级排序...

    uthash开源的hash函数实现

    UTHASH 是一个开源的 C 语言库,提供了一种简单且高效的哈希表实现,用于在 C 代码中快速查找和管理数据结构。这个库的主要功能是提供一个宏定义的集合,可以方便地将结构体转化为哈希表,进而进行添加、删除、查找...

    Java-codes.rar_HASH JAVA_huffman

    在给定的“Java-codes.rar_HASHJAVA_huffman”压缩包中,包含了多个与Java编程相关的示例代码,主要涉及哈夫曼编码(Huffman Coding)、快速排序(Quicksort)、哈希表(Hash)以及一种名为“q_sort”的排序算法。...

    PersistentIdealHashTree-Java实现

    通过以上分析,我们可以看出,PersistentIdealHashTree的Java实现不仅涉及到数据结构的设计和优化,还需要考虑并发编程中的线程安全问题。理解并掌握这种数据结构的实现原理,对于提升Java程序员在大数据处理和并发...

    Hash map 哈希表

    哈希表,也被称为Hash Map,是计算机科学中一种高效的数据结构,用于存储键值对。它通过一种称为哈希函数的过程将键映射到数组的特定位置,从而实现快速的查找、插入和删除操作。在哈希表中,查找时间通常接近常数...

    在Java中运用Hashtables.rar_hash table

    在Java编程语言中,哈希表(Hash Table)是一种常用的数据结构,它的实现通常通过`Hashtable`类。这个数据结构提供了快速的插入、删除和查找操作,其平均时间复杂度为O(1)。`Hashtable`是Java集合框架的一部分,位于...

    Java算法题,数据结构分析和实现.zip

    在本压缩包“Java算法题,数据结构分析和实现.zip”中,主要涵盖了与Java编程相关的算法题目以及数据结构的深入分析和实现。数据结构是计算机科学中的核心概念,它研究如何有效地组织和存储数据,以便高效地进行访问...

    Java思维导图xmind文件+导出图片

    redis使用常见问题及性能优化思路 redis高可用及高并发实战 缓存击穿、缓存雪崩预防策略 Redis批量查询优化 Redis高性能集群之Twemproxy of Redis 数据存储 MongoDB NOSQL简介及MongoDB支持的数据类型分析 ...

    数据结构 java 软件工程笔试

    5. Hash表查找效率: 最好的情况下,哈希表的查找复杂度为O(1),这是理想情况下的常数时间复杂度,因为哈希函数能直接定位到数据。 --- 第二部分软件工程知识点: 1. 软件能力成熟度模型(CMM): CMM有5个成熟...

    最快的排序算法 javahash实现-Java-哈希算法-最快的实现,排序算法数据结构

    8. 数据结构的选择:在选择数据结构时,需要考虑到ハシ表、树形结构、图结构等不同的数据结构的优缺点,并选择合适的数据结构来实现哈希算法。 9. 安全性问题:在实现哈希算法时,需要考虑到安全性问题,例如选择...

    Java数据结构和算法(第二版)

    根据提供的文件信息,“Java数据结构和算法(第二版)”这本书主要聚焦于使用Java语言来讲解数据结构与算法的相关知识。接下来,我们将基于这个标题、描述以及部分可见内容,提炼并扩展出一些重要的知识点。 ### ...

    数据结构(C语言版)\Java数据结构和算

    1.5 性能分析 1.6 性能度量 1.7 参考文献和选读材料 第2章 数组和结构 2.1 数组 2.2 数组的动态存储分配 2.3 结构体和联合体 2.4 多项式 2.5 稀松矩阵 2.6 多维数组的表示 2.7 字符串 2.8 参考文献和选读...

Global site tag (gtag.js) - Google Analytics