get() 方法一样快。 另一方面,containsValue() 方法很可能需要扫描 Map 中的值,因此它的速度可能比较慢。 表 4: Map 访问和测试方法: 这些方法检索有关 Map 内容的信息但不更改 Map 内容。 get(Object key)返回与指定键关联的值containsKey(Object key)如果 Map 包含指定键的映射,则返回 truecontainsValue(Object value)如果此 Map 将一个或多个键映射到指定值,则返回 trueisEmpty()如果 Map 不包含键-值映射,则返回 truesize()返回 Map 中的键-值映射的数目 对使用 containsKey() 和 containsValue() 遍历 HashMap 中所有元素所需时间的测试表明,containsValue() 所需的时间要长很多。 实际上要长几个数量级! (参见图 1 和图 2,以及随附文件中的 。 因此,如果 containsValue() 是应用程序中的性能
问题,它将很快显现出来,并可以通过监测您的应用程序轻松地将其识别。 这种情况下,我相信您能够想出一个有效的替换方法来实现 containsValue() 提供的等效功能。 但如果想不出办法,则一个可行的解决方案是再创建一个 Map,并将第一个 Map 的所有值作为键。 这样,第一个 Map 上的 containsValue() 将成为第二个 Map 上更有效的 containsKey()。 图 1: 使用 JDeveloper 创建并运行 Map 测试类 图 2: 在 JDeveloper 中使用执行监测器进行的性能监测查出应用
程序中的瓶颈 核心 Map Java 自带了各种 Map 类。 这些 Map 类可归为三种类型: 1.
通用 Map,用于在应用程序中管理映射,通常在 java.util
程序包中实现 o
HashMap o
Hashtable o
Properties o
LinkedHashMap o
IdentityHashMap o
TreeMap o
WeakHashMap o
ConcurrentHashMap 2.
专用 Map,您通常不必亲自创建此类 Map,而是通过某些其他类对其进行访问 o
java.util.jar.Attributes o
javax.print.attribute.standard.PrinterStateReasons o
java.security.Provider o
java.awt.RenderingHints o
javax.swing.UIDefaults 3.
一个用于帮助实现您自己的 Map 类的抽象类 o
AbstractMap 内部哈希: 哈希映射技术 几乎所有通用 Map 都使用哈希映射。 这是一种将元素映射到数组的非常简单的机制,您应了解哈希映射的工作原理,以便充分利用 Map。 哈希映射结构由一个存储元素的内部数组组成。 由于内部采用数组存储,因此必然存在一个用于确定任意键访问数组的索引机制。 实际上,该机制需要提供一个小于数组大小的整数索引值。 该机制称作哈希函数。 在 Java 基于哈希的 Map 中,哈希函数将对象转换为一个适合内部数组的整数。 您不必为寻找一个易于使用的哈希函数而大伤脑筋: 每个对象都包含一个返回整数值的 hashCode() 方法。 要将该值映射到数组,只需将其转换为一个正值,然后在将该值除以数组大小后取余数即可。 以下是一个简单的、适用于任何对象的 Java 哈希函数 int hashvalue = Maths.abs(key.hashCode()) % table.length; (% 二进制运算符(称作模)将左侧的值除以右侧的值,然后返回整数形式的余数。) 实际上,在 1.4 版发布之前,这就是各种基于哈希的 Map 类所使用的哈希函数。 但如果您查看一下代码,您将看到 int hashvalue = (key.hashCode() & 0x7FFFFFFF) % table.length; 它实际上是使用更快机制获取正值的同一函数。 在 1.4 版中,HashMap 类实现使用一个不同且更复杂的哈希函数,该函数基于 Doug Lea 的 util.concurrent
程序包(稍后我将更详细地再次介绍 Doug Lea 的类)。 图 3: 哈希工作原理 该图介绍了哈希映射的基