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

Java中的Hashtable的用法

Java中的Hashtable的用法:Java包含两个类,java.util.Hashtable和java.util.HashMap,它们提供了一个多种用途的hashtable机制。Hashtabl


Java中的Hashtable的用法:

Java包含两个类,java.util.Hashtable 和java.util.HashMap,它们提供了一个多种用途的hashtable机制。Hashtable和HashMap对象可以让你把一个key和一个value结合起来,并用put() 方法把这对key/value输入到表中。然后你可以通过调用get()方法,把key作为参数来得到这个value(值)。只要满足两个基本的要求,key和value可以是任何对象。注意,因为key和value必须是对象,所以原始类型(primitive types)必须通过运用诸如Integer(int)的方法转换成对象。下面是一段简单的示例代码:
1. 先创建一个hashtable,保存了1, 2, 3三个对象。
Hashtable numbers = new Hashtable();
numbers.put("one", new Integer(1));
numbers.put("two", new Integer(2));
numbers.put("three", new Integer(3));
2. 查找
Integer n = (Integer)numbers.get("two");
if (n != null) {
System.out.println("two = " + n);
}
为了将一个特定类的对象用做一个key,这个类必须提供两个方法,equals() 和 hashCode()。这两个方法在java.lang.Object中,所以所有的类都可以继承这两个方法;但是,这两个方法在Object类中的实现一般没什么用,所以你通常需要自己重载这两个方法。
Equals()方法把它的对象同另一个对象进行比较,如果这两个对象代表相同的信息,则返回true。该方法也查看并确保这两个对象属于相同的类。如果两个参照对象是完全一样的对象,Object.equals()返回true,这就说明了为什么这个方法通常不是很适合的原因。在大多数情况下,你需要一个方法来一个字段一个字段地进行比较,所以我们认为代表相同数据的不同对象是相等的。
HashCode()方法通过运用对象的内容执行一个哈希函数来生成一个int值。Hashtable和HashMap用这个值来算出一对key/value位于哪个bucket(哈希元)(或列表)中。


如果你想创建一个hashtable,这个hashtable运用你自己定义的一个类的对象作为key,那么你应该确信这个类的equals()和hashCode()方法提供有用的值。首先查看你扩展的类,确定它的实现是否满足你的需求。如果没有,你应该重载方法。
任何equals()方法的基本设计约束是,如果传递给它的对象属于同一个类,而且它的数据字段设定为表示同样数据的值,那么它就应该返回true。你也应该确信,如果传递一个空的参数给该方法,那么你的代码返回false:public boolean equals(Object o)
{
if ( (o == null)
|| !(o instanceof myClass))
{
return false;
}
}

另外,在设计一个hashCode()方法时,应该记住一些规则。首先,该方法必须为一个特定的对象返回相同的值,而不管这个方法被调用了多少次(当然,只要对象的内容在调用之间没有改变,在将一个对象用做一个hashtable的key时,应该避免这一点)。第二,如果由你的equals()方法定义的两个对象是相等的,那么它们也必须生成相同的哈希码。第三,这更像是一个方针,而不是一个原则,你应该设法设计方法,使它为不同的对象内容生成不同的结果。如果偶尔不同的对象正好生成了相同的哈希码,这也不要紧。但是,如果该方法只能返回范围在1到10的值,那么只能用10个列表,而不管在hashtable中有多少个列表。


Hashtable和HashMap
Hashtable和HashMap类有三个重要的不同之处。第一个不同主要是历史原因。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。
也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这就意味着,虽然你可以不用采取任何特殊的行为就可以在一个多线程的应用程序中用一个Hashtable,但你必须同样地为一个HashMap提供外同步。一个方便的方法就是利用Collections类的静态的synchronizedMap()方法,它创建一个线程安全的Map对象,并把它作为一个封装的对象来返回。这个对象的方法可以让你同步访问潜在的HashMap。这么做的结果就是当你不需要同步时,你不能切断Hashtable中的同步(比如在一个单线程的应用程序中),而且同步增加了很多处理费用。
第三点不同是,只有HashMap可以让你将空值作为一个表的条目的key或value。HashMap中只有一条记录可以是一个空的key,但任意数量的条目可以是空的value。这就是说,如果在表中没有发现搜索键,或者如果发现了搜索键,但它是一个空的值,那么get()将返回null。如果有必要,用containKey()方法来区别这两种情况。
一些资料建议,当需要同步时,用Hashtable,反之用HashMap。但是,因为在需要时,HashMap可以被同步,HashMap的功能比Hashtable的功能更多,而且它不是基于一个陈旧的类的,所以有人认为,在各种情况下,HashMap都优先于Hashtable。


Hashtable性能

影响hashtable功效的主要因素就是表中列表的平均长度,因为平均搜索时间与这个平均长度直接相关。很显然,要减小平均长度,你必须增加hashtable中列表的数量;如果列表数量非常大,以至于大多数列表或所有列表只包含一条记录,你就会获得最佳的搜索效率。然而,这样做可能太过分了。如果你的hashtable的列表数远远多于数据条目,那你就没有必要做这样的内存花费了,而在一些情况下,人们也不可能接受这样的做法。
在我们前面的例子中,我们预先知道我们有多少条记录1,000。知道这点后,我们就可以决定我们的hashtable应该包含多少个列表,以便达成搜索速度和内存使用效率之间最好的折中方式。然而,在许多情况下,你预先不知道你要处理多少条记录;数据被读取的文件可能会不断扩大,或者记录的数量可能一天一天地发生很大的变化。
随着条目的增加,Hashtable和HashMap类通过动态地扩展表来处理这个问题。这两个类都有接受表中列表最初数量的构造器,和一个作为参数的负载系数(load factor):public Hashtable(
int initialCapacity,
float loadFactor)
public HashMap(
int initialCapacity,
float loadFactor)
将这两个数相乘计算出一个临界值。每次给哈希表添加一个新的条目时,计数就被更新,当计数超过临界值时,表被重新设置(rehash)。(列表数量增加到以前数量的两倍加1,所有的条目转移到正确的列表中。)缺省的构造器设定最初的容量为11,负载系数是0.75,所以临界值是8。当第九条记录被添加到表中时,就重新调整哈希表,使其有23个列表,新的临界值将是17(23*0.75的整数部分)。你可以看到,负载系数是哈希表中平均列表数量的上限,这就意味着,在缺省情况下,哈希表很少会有许多包含不只一条记录的列表。比较我们最初的例子,在那个例子中,我们有1,000条记录,分布在10个列表中。如果我们用缺省值,这个表将会扩展到含有1,500多个列表。但你可以控制这点。如果用负载系数相乘的列表数量大于你处理的条目数,那么表永远不会重制,所以我们可以仿效下面的例子:// Table will not rehash until it
// has 1,100 entries (10*110):
Hashtable myHashTable =
new Hashtable(10, 110.0F);
你可能不想这么做,除非你没有为空的列表节省内存,而且不介意额外的搜索时间,这可能在嵌入系统中会出现这种情况。然而,这种方法可能很有用,因为重新设置很占用计算时间,而这种方法可以保证永远不会发生重新设置这种情况。
注意,虽然调用put()可以使表增大(列表数量增加),调用remove()不会有相反的结果。所以,如果你有一个大的表,而且从中删除了大部分条目,结果你会有一个大的但是大部分是空的表。
Hashtable和HashMap
Hashtable和HashMap类有三个重要的不同之处。第一个不同主要是历史原因。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。
也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这就意味着,虽然你可以不用采取任何特殊的行为就可以在一个多线程的应用程序中用一个Hashtable,但你必须同样地为一个HashMap提供外同步。一个方便的方法就是利用Collections类的静态的synchronizedMap()方法,它创建一个线程安全的Map对象,并把它作为一个封装的对象来返回。这个对象的方法可以让你同步访问潜在的HashMap。这么做的结果就是当你不需要同步时,你不能切断Hashtable中的同步(比如在一个单线程的应用程序中),而且同步增加了很多处理费用。
第三点不同是,只有HashMap可以让你将空值作为一个表的条目的key或value。HashMap中只有一条记录可以是一个空的key,但任意数量的条目可以是空的value。这就是说,如果在表中没有发现搜索键,或者如果发现了搜索键,但它是一个空的值,那么get()将返回null。如果有必要,用containKey()方法来区别这两种情况。
一些资料建议,当需要同步时,用Hashtable,反之用HashMap。但是,因为在需要时,HashMap可以被同步,HashMap的功能比Hashtable的功能更多,而且它不是基于一个陈旧的类的,所以有人认为,在各种情况下,HashMap都优先于Hashtable。

关于Properties
有时侯,你可能想用一个hashtable来映射key的字符串到value的字符串。DOS、Windows和Unix中的环境字符串就有一些例子,如key的字符串PATH被映射到value的字符串C:WINDOWS;C:WINDOWSSYSTEM。Hashtables是表示这些的一个简单的方法,但Java提供了另外一种方法。
Java.util.Properties类是Hashtable的一个子类,设计用于String keys和values。Properties对象的用法同Hashtable的用法相象,但是类增加了两个节省时间的方法,你应该知道。
Store()方法把一个Properties对象的内容以一种可读的形式保存到一个文件中。Load()方法正好相反,用来读取文件,并设定Properties对象来包含keys和values。
注意,因为Properties扩展了Hashtable,你可以用超类的put()方法来添加不是String对象的keys和values。这是不可取的。另外,如果你将store()用于一个不包含String对象的Properties对象,store()将失败。作为put()和get()的替代,你应该用setProperty()和getProperty(),它们用String参数。
import java.util.*;
class HashMapTest
{
        public static void printElements(Collection c,HashMap hm)
        {
                Iterator it=c.iterator();
                while(it.hasNext())
                {
                        Object key1=it.next();
                        System.out.println(key1+" = "+hm.get(key1));
                }
        }
        public static void main(String[] args)
        {
                HashMap hm=new HashMap();
                                
                Student s1=new Student(1,"zhang3");
                Student s2=new Student(2,"li4");
                Student s3=new Student(3,"wang5");
                Student s4=new Student(1,"zhang3");
                
                hm.put(s1,"123");
                hm.put(s2,"456");
                hm.put(s3,"789");
                hm.put(s4,"321");
                Set keys=hm.keySet();
                System.out.println("Key:");
                printElements(keys,hm);                                
        }
}

class Student
{
        int num;
        String name;
        Student(int num,String name)
        {
                this.num=num;
                this.name=name;
        }
                
        public int hashCode()
        {
                return num*name.hashCode();
        }
                
        public boolean equals(Object o)
        {
                Student s=(Student)o;
                return num==s.num && name.equals(s.name);
        }
        
        public String toString()
        {
                return num+":"+name;
        }
}


推荐阅读
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • HashTable与ConcurrentHashMap均可实现HashMap的功能,对外提供了键值对存储的数据结构。但是在内部结构及实现上有何区别,性能上的差异到底在哪里又是如何导致的 ... [详细]
  • 类Hashtable<K,V>所有已实现的接口:Serializable,Cloneable,Map<K,V>此类实现一个哈希表,该哈希表将键映 ... [详细]
  • hashmap线程不安全允许有null的键和值效率高一点、方法不是Synchronize的要提供外同步有containsvalue和containsKey方法HashMap是Java1 ... [详细]
  • 我有一个xml文件,里面的数据想放入自定义类里存入HashTable里面,不知道有没有哪为高手有这方面的例子,希望能解小弟一时之困!谢谢! ... [详细]
  • 1、连接操作相关的命令quit:关闭连接(connection)auth:简单密码认证2、对value操作的命令exists(key):确认一个key是否存在del(key):删除一个keytype( ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 【Windows】实现微信双开或多开的方法及步骤详解
    本文介绍了在Windows系统下实现微信双开或多开的方法,通过安装微信电脑版、复制微信程序启动路径、修改文本文件为bat文件等步骤,实现同时登录两个或多个微信的效果。相比于使用虚拟机的方法,本方法更简单易行,适用于任何电脑,并且不会消耗过多系统资源。详细步骤和原理解释请参考本文内容。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • java给iphone应用实现推送
    根据公司项目所需,需要对iphone应用进行消息推送,一开始选的是php,但是php语言知识略懂,开发起来比较麻烦,所有就用比较熟悉的java语言进行消息推送。需要依赖的jar包: ... [详细]
  • ReactorCoolingTimeLimit:5SecondsMemoryLimit:32768KBSpecialJudge ... [详细]
  • 程序把一个文本文件在屏幕上缓慢输出,完全输出后再从头循环输出修改后可以使用的程序源代码(还是不完善:还不能实现从一侧飞入的效果,容易出错):unitUnit1;interfaceus ... [详细]
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社区 版权所有