除了类集, Java 2还在java.util中增加了映射。
**映射(map)**是一个存储关键字和值的关联或者说是关键字/值对的对象。
给定一个关键字,可以得到它的值。 关键字和值都是对象。 关键字必须是唯一的。 但值是可以重复的。有些映射可以接收null关键字和null值。而有的则不行。
java.util
Interface Map
Type Parameters:
K - the type of keys maintained by this map
V - the type of mapped values
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
(一个对象会将键映射到值上,一个map不能包含重复的键,一个键最多映射到一个值上)
关键字(key)是以后用于检索值的对象。给定一个关键字和一个值,可以存储这个值到一个Map对象中。当这个值被存储以后,就可以使用它的关键字来检索它。当调用的映射中没有项存在时,其中的几种方法会引发一个NoSuchElementException异常。而当对象与映射中的元素不兼容时,引发一个ClassCastException异常。如果试图使用映射不允许使用的null对象时,则引发一个NullPointerException异常。当试图改变一个不允许修改的映射时,则引发一个UnsupportedOperationException异常
• HashMap类使用散列表实现Map接口。这允许一些基本操作如get( )和put( )的运行时间保持恒定,即便对大型集合,也是这样的。
• 下面的构造函数定义为:
构造方法 | 解释 |
---|---|
HashMap( ) | 第一种形式构造一个默认的散列映射。 |
HashMap(Map m) | 第二种形式用m的元素初始化散列映射。 |
HashMap(int capacity) | 第三种形式将散列映射的容量初始化为capacity。 |
HashMap(int capacity, float fillRatio) | 第四种形式用它的参数同时初始化散列映射的容量和填充比。容量和填充比的含义与前面介绍的HashSet中的容量和填充比相同。 |
HashMap实现Map并扩展AbstractMap。它本身并没有增加任何新的方法
应该注意的是散列映射并不保证它的元素的顺序。因此,元素加入散列映射的顺序并不一定是它们被迭代函数读出的顺序
映射循环使用两个基本操作: get( )和put( )。
使用put( )方法可以将一个指定了关键字和值的值加入映射。为了得到值,可以通过将关键字作为参数来调用get( )方法。调用返回该值。
V put(K key, V value)
Associates the specified value with the specified key in this map (optional operation).
(在这个映射中将指定的值和指定的关键字建立联系)(可选操作)
If the map previously contained a mapping for the key, the old value is replaced by the specified value.
(如果映射中有这个关键字,那么就用新的值替换旧的值)
(A map m is said to contain a mapping for a key k if and only if m.containsKey(k) would return true.)
package fourtyEighth;
import java.util.HashMap;
public class MapTest1 {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("a", "zhangsan");
map.put("b", "lisi");
map.put("c", "wangwu");
map.put("a", "zhaoliu");
System.out.println(map);
}
}
结果是:
{a=zhaoliu, b=lisi, c=wangwu}
后put的值将之前的值替换掉。
V get(Object key)
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. (返回一个值指定的键映射的值,或者当映射中没有这个关键字时返回空)
package fourtyEighth;
import java.io.ObjectInputStream.GetField;
import java.util.HashMap;
public class MapTest1 {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("a", "zhangsan");
map.put("b", "lisi");
map.put("c", "wangwu");
map.put("a", "zhaoliu");
//System.out.println(map);
String value = (String)map.get("b");
System.out.println(value);
System.out.println("----------");
String value2 = (String)map.get("d");
System.out.println(value2);
}
}
结果是:
lisi
null
null可以强转为任意类型
package fourtyEighth;
import java.util.HashMap;
public class HashMapTest2 {
public static void main(String[] args) {
HashMap map = new HashMap();
String str = new String("zhangsan");
map.put("a", str);
map.put("b", str);
System.out.println(map);
}
}
结果是:
{a=zhangsan, b=zhangsan}
Set keySet()
Returns a Set view of the keys contained in this map.
(返回一个包含在map中的键的set视图)
The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
(这个集合是map来维护的,因此对map的修改就会反应的set上,反之亦然)
Collection values()
Returns a Collection view of the values contained in this map.
(返回了一个包含在map中的值的collection视图)
The collection is backed by the map, so changes to the map are reflected in the collection, and vice-versa.
(这个集合是map来维护的,因此对map的修改就会反应到collection上,反之亦然)
Map(映射): Map 的 keySet()方法会返回 key 的集合,因为 Map 的键是不能重复的,因此 keySet()方法的返回类型是 Set;而 Map 的值是可以重复的,因此 values()方法
的返回类型是 Collection,可以容纳重复的元素。
package fourtyEighth;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class MapTest3 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("a", "aa");
map.put("b", "bb");
map.put("c", "cc");
map.put("d", "dd");
map.put("e", "ee");
Set<String> set = map.keySet();
for(Iterator<String> iter = set.iterator();iter.hasNext();) {
String key = (String)iter.next();
String value = (String)map.get(key);
System.out.println(key + "=" + "value");
}
}
}
结果是:
a=value
b=value
c=value
d=value
e=value
我们可以通过run》Run Configuration 》改变自变量中的值来给args赋值,可以用“”将字符串括起来来表示一个值,我们作这样的一个例子,通过给args传值,来统计每个值出现的次数。
package fourtyEighth;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class MapTest4 {
public static void main(String[] args) {
HashMap map = new HashMap();
for (int i = 0; i < args.length; i++) {
if(map.get(args[i]) == null) {
map.put(args[i], 1);
}
else {
int in = (Integer)map.get(args[i]);
in = in + 1;
map.put(args[i], in);
}
}
Set set = map.keySet();
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
String key = (String)iterator.next();
Integer value = (Integer)map.get(key);
System.out.println(key + "=" + value);
}
}
}
结果是:
world=2
hello=3
welcome=1
public static interface Map.Entry
A map entry (key-value pair).
The Map.entrySet method returns a collection-view of the map, whose elements are of this class. (Map.entrySet方法返回一个映射的集合视图,其元素属于这个类。)
The only way to obtain a reference to a map entry is from the iterator of this collection-view. (获取对映射条目的引用的唯一方法是从此集合视图的迭代器中获取。)
These Map.Entry objects are valid only for the duration of the iteration; more formally, the behavior of a map entry is undefined if the backing map has been modified after the entry was returned by the iterator, except through the setValue operation on the map entry.(这些Map.Entry对象仅在迭代期间有效;更正式地说,如果在迭代器返回条目之后修改了支持映射,则映射条目的行为没有定义,除非通过映射条目的setValue操作。)
Map.Entry接口使得可以操作映射的输入。回想由Map接口说明的entrySet( )方法,调用该方法返回一个包含映射输入的集合(Set)。这些集合元素的每一个都是一个Map.Entry对象。
Set
Returns a Set view of the mappings contained in this map.
Nested Class Summary | |
---|---|
static interface | Map.Entry |
Method Summary | |
---|---|
boolean equals(Object o) | Compares the specified object with this entry for equality. |
K getKey() | Returns the key corresponding to this entry. |
V getValue() | Returns the value corresponding to this entry. |
package fourtyNineth;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapTest5 {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("a", "aa");
map.put("b", "bb");
map.put("c", "cc");
map.put("d", "dd");
Set set = map.entrySet();
for(Iterator iter = set.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
String value = (String)entry.getValue();
System.out.println(key + ":" + value);
}
}
}
结果是:
a:aa
b:bb
c:cc
d:dd
entrySet是是直接获得一个entry对象包含键和值,然后再getkey输出键,getkey输出值,用keySet是获取键,然后用键再获取值,这两种方式底层都是一样的,开发中都要掌握。
package fiftieth;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
/**
* 随机生成 50 个数字(整数),每个数字的范围是[10, 50],统计每个数字出现的次数以及出现次数最多的数字与它的个数,
* 最后将每个数字及其出现次数打印出来,如果某个数字出现次数为 0,则不要打印它。打印时按照数字的升序排列。
*
* @author 张议
*
*/
public class RandomTest {
public static void main(String[] args) {
Map map = new TreeMap();//存储数字及其出现的次数(key为数字,value为数字出现的次数)
Random random = new Random();
for(int i = 0; i < 50; i++) {
int number = random.nextInt(41) + 10;
Integer in = new Integer(number);//装箱
if(map.get(in) == null) {
map.put(in, new Integer(1));
}
else {
int value = ((Integer)map.get(in)).intValue();
map.put(in, new Integer(value + 1));
}
}
Collection cols = map.values();
Integer maxOccurs = (Integer)Collections.max(cols);
Set set = map.entrySet();
List list = new ArrayList();//存储出现次数最大的数字
for(Iterator iter = set.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry)iter.next();
Integer key = (Integer)entry.getKey();
Integer value = (Integer)entry.getValue();
if(value.intValue() == maxOccurs.intValue()) {
list.add(key);
}
System.out.println(key + ":" + value);
}
System.out.println("出现次数最多次数为:"+ maxOccurs);
System.out.println("这些数字分别为:");
for(Iterator iterator = list.iterator(); iterator.hasNext();) {
System.out.println(iterator.next());
}
}
}
結果是:
10:3
12:1
14:1
15:2
18:1
21:2
22:1
24:2
25:4
26:2
27:1
28:2
30:4
31:1
32:1
33:1
34:2
35:1
36:1
38:2
39:2
40:3
42:1
43:1
45:5
46:2
48:1
出现次数最多次数为:5
这些数字分别为:
45
映射不是类集,但可以获得映射的类集“视图” 。为了实现这种功能,可以使用entrySet( )方法,
Set
Returns a Set view of the mappings contained in this map.
它返回一个包含了映射中元素的集合(Set)。为了得到关键字的类集“视图” ,可以使用keySet( )方法。
Set keySet()
Returns a Set view of the keys contained in this map.
为了得到值的类集“视图” ,可以使用values( )方法。类集“视图” 是将映射集成到类集框架内的手段
Collection values()
Returns a Collection view of the values contained in this map.
java.util
Interface SortedMap
Type Parameters:
K - the type of keys maintained by this map
V - the type of mapped values
SortedMap接口扩展了Map,它确保了各项按关键字升序排序。当调用映射中没有的项时,其中的几种方法引发一个NoSuchElement Exception异常。当对象与映射中的元素不兼容时,则引发一个ClassCastException异常。当试图使用映射不允许使用的null对象时,则引发一个NullPointerException异常。
排序映射允许对子映射(换句话说,就是映射的子集)进行高效的处理。使用
**headMap( ), tailMap( )或subMap( )方法可以获得子映射。调用firstKey( )方法可以获得集合的第一个关键字。而调用lastKey( )**方法可以获得集合的最后一个关键字
当写完一个小的模块时,不要着急往下写,立刻去做测试,当我们讲完单元测试时,我们可以更好的作测试,现在我们可以依靠运行来作为测试,千万不要一个模块的功能很多全写完再做测试,这是愚蠢的行为,小步前进,增量开发,逐步迭代,把一个大的问题切分成小的模块,每个模块完成后做测试,没问题后再开发接下来的。