容器深入研究 --- 理解Map

通常的:

映射表(也称关联数组)的基本思想是它维护的键-值(对)关联,因此你可以使用键来查找值。

标准的Java类库中包含了Map的几种实现,包括:HashMap,TreeMap,LinkedHashMap,WeakHashMap,ConcurrentHashMap,IdentityHashMap。

它们都有同样的基本接口Map,但是行为特性各不相同,这表现在效率、键值对的保存及呈现次序、对象的保存周期、映射表如何在多线程程序中工作的判定“键”等价的策略方面。Map接口实现的数量应该让你感觉到这种工具的重要性。

你可以获的对Map更深入的理解,这有助于观察关联数组是如何创建的。下面是一个极其简单的实现。

class AssociativeArray<K,V> {
	private Object[][] pairs;
	private int index;

	public AssociativeArray(int length) {
		pairs = new Object[length][2];
	}

	public void put(K key, V value) {
		if (index >= pairs.length) {
			throw new ArrayIndexOutOfBoundsException();
		}
		pairs[index++] = new Object[]{key, value};
	}

	public V get(K key) {
		for (int i = 0; i < index; i ++) {
			if (key.equals(pairs[i][0])) {
				return (V) pairs[i][1];
			}
		}
		return null;
	}

	@Override
	public String toString() {
		StringBuffer result = new StringBuffer();
		for (int i = 0; i < index; i++) {
			result.append(pairs[i][0].toString());
			result.append(":");
			result.append(pairs[i][1].toString());
			if (i < index - 1) {
				result.append("\n");
			}
		}
		return result.toString();
	}
}

上面的本版是简单性的、缺乏效率性的,并且由于具有固定的尺寸显得够不灵活。

性能:

性能是映射表中的一个重要问题,当在get()中使用线性搜索时,执行速度回相当的慢,而这正是HashMap提高速度的地方。

HashMap使用了特殊的值,称作散列码,来取代对键的缓慢搜索。散列码是“相对唯一”的、用以代表对象的int值,它是通过将该对象的某些信息进行转换搜索而成的。

hashCode()是根类Object中的方法,因此所有Java对象都能产生散列码,HashMap就是使用对象的hashCode()进行快速查询的,此方法可以显著的提高性能

下面是基本的Map实现。在HashMap上打星号表示如果没有其他的限制,它就应该成为你的默认选择,因为它对速度进行了优化。其他的都强调其他的特性,因此都不如HashMap快。

HashMap:

Map基于散列表的实现(它取代了HashTable)。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量和负载因子,以调整容器的性能

LinkedHashMap:

类似于HashMap,但是迭代遍历时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点;而在迭代访问时反映更快,因为它使用的链表维护内部次序

TreeMap:

基于红黑树的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparable或者Comparator决定)。TreeMap特点在于,所得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。

WeakHashMap:

弱键(weak key)映射,允许释放映射所指向的对象;这是为解决某类特殊问题而设计的。如果映射之外没有引用指向某个“键”,则此“键”可以被垃圾回收器回收。

ConcurrentHashMap:

一种线程安全的Map,它不涉及同步加锁。

IdentityHashMap:

使用==代替equals()对“键”进行比较的散列映射。专为解决特殊问题设计的。

散列是映射中存储元素的最常用的方式。

对Map中使用的键的要求与对Set中的元素的要求一样。任何键都必须有一个equals()方法;如果键被用于散列Map,那么它必须还具有恰当的hashCode()方法;如果键被用于TreeMap它必须实现Comparable。

SortedMap:

用SortedMap(TreeMap时期现阶段的唯一实现),可以确保键处于排序状态。这使得它具有额外的功能,这些功能是由SortedMap接口中的下列方法提供给的:

 Comparator<? super
K>
comparator()

返回对此映射中的键进行排序的比较器;如果此映射使用键的自然顺序,则返回
null

 Set<Map.Entry<K,V>> entrySet()

返回在此映射中包含的映射关系的 Set 视图。

 K firstKey()

返回此映射中当前第一个(最低)键。

 SortedMap<K,V> headMap(K toKey)

返回此映射的部分视图,其键值严格小于 toKey

 Set<K> keySet()

返回在此映射中所包含键的 Set 视图。

 K lastKey()

返回映射中当前最后一个(最高)键。

 SortedMap<K,V> subMap(K fromKey,
K toKey)

返回此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)。

 SortedMap<K,V> tailMap(K fromKey)

返回此映射的部分视图,其键大于等于 fromKey

 Collection<V> values()

返回在此映射中所包含值的 Collection 视图。

LindedHashMap:

为了提高速度,LinkedHashMap散列化所有的元素,但是在遍历键值对时,却又以元素的插入顺序返回键值对(System.out.println())。

此外,可以在构造器中设定LinkedHashMap,使之采用基于访问最近最少使用(LRU)算法,于是没有访问过的(可被看做需要删除的)元素就会出现在队列的掐面,对于需要定期清理元素以节省空间的程序来说,此功能是很容易实现的。

容器深入研究 --- 理解Map,布布扣,bubuko.com

时间: 2024-10-26 14:43:16

容器深入研究 --- 理解Map的相关文章

容器深入研究 --- 散列与散列码(一)

通常的: 当标准类库中的类被作用HashMap的键.它用的很好,因为它具备了键所需的全部性质. 当你自己创建用作HashMap的键的类,有可能会忘记在其中放置必须的方法,而这时通常会犯的一个错误. 例如:考虑一个天气系统,将Groundhog对象与Prediction对象联系起来. class Groundhog { protected int number; public Groundhog(int n) { number = n; } public String toString() { r

容器深入研究 --- 散列与散列码(二)

为速度而散列: SlowMap.java说明了创建一个新的Map并不困难.但正如它的名称SlowMap所示,它不会很快,如果有更好的选择就应该放弃它.它的问题在于对键的查询,键没有按照任何特定的顺序保存,所以只能使用简单的线性查询,而线性查询是最慢的查询方式. 散列的价值在于速度: 散列使得查询得以快速进行.由于瓶颈在于键的查询速度,因此解决方案之一就是保持键的排序状态,然后使用Collections.binarySearch()进行查询. 散列则更进一步,它将键保存在某处,以便能够很快的找到.

Thinking in Java:容器深入研究

1.虚线框表示Abstract类,图中大量的类的名字都是以Abstract开头的,它们仅仅是部分实现了特定接口的工具,因此创建时能够选择从Abstract继承. Collections中的实用方法:挑几个经常使用的: 1. reverse(List):逆转次序 2. rotate(List,int distance)全部元素向后移动distance个位置,将末尾元素循环到前面来(用了三次reverse) 3.sort(List,Comparator) 排序,可依照自己的Comparator 4.

深度理解map hash_map set

map VS hash_map 1)map存储的时候为排好序的,所以输出时候也是排序的.而hash_map不是的. 2)map具有稳定性,底层存储为树,这种算法差不多相当与list线性容器的折半查找的效率一样,都是O (log2N). hash_map使用hash表来排列配对,hash表是使用关键字来计算表位置.当这个表的大小合适,并且计算算法合适的情况下,hash表的算法复杂度为O(1)的,但是这是理想的情况下的,如果hash表的关键字计算与表位置存在冲突,那么最坏的复杂度为O(n). 3) 

java 容器Collection List Set Map概述

对JAVA的集合的理解是想对于数组 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型) JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! JAVA集合只能存放引用类型的的数据,不能存放基本数据类型. JAVA集合主要分为三种类型: Set(集) List(列表) Map(映射) Collection 接口 Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法. Set 和

Java编程思想——第17章 容器深入研究(two)

六.队列 排队,先进先出.除并发应用外Queue只有两个实现:LinkedList,PriorityQueue.他们的差异在于排序而非性能. 一些常用方法: 继承自Collection的方法: add 在尾部增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常 remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常 element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementExce

容器深入研究 --- 散列与散列码(三)

如何覆盖hashCode(): 明白了如何散列之后,编写自己的hashCode()就更有意义了. 首先,你无法控制bucket数组的下标值的产生.这个值依赖于具体的HashMap对象的容量,而容量的改变与容器的充满程度和负载因子有关.hashCode()生成的结果,经过处理后称为桶位的下标. 设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值.如果在将一个对象用put()添加进HashMap时产生一个hashCode()值,而用get()

容器的研究思路

容器的研究思路 为什么研究容器 容器是JDK里的基础功能,平时使用得较多. 容器相对简单,比较容易研究 已经有很多人对容器进行了研究,相关资料比较齐全 容器是什么,要研究那些特性 容器是一段程序,是一系列的对象. 作为程序,它由 数据结构+算法构成 作为对象,它由 属性+方法构成 作为类,它有自己的继承树 容器有很多的工具类,如collections.Arrays.Iterator等等 怎么去研究容器 评价软件的4个因素:可维护性,可靠性,移植性,效率 如何去测试评估程序的特性 程序的并发性能

Java容器(List、Map、Set、Iterator)

容器是一个Java 所编写的程序,原先必须自行编写程序以管理对象关系,现在容器都会自动帮您做好. List特点:元素有放入顺序,元素可重复 Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的) Map特点:元素按键值对存储,无放入顺序 . 一.List接口 ArrayList:线程不安全,效率高. 底层实现是数组,查询块,修改删除慢. LinkedList: 线程不安全,效率高. 底层实现是链表,查询