Map 是强大的编程工具。一组成对的“键值对”对象,允许使用键来查找值。映射表循序我们使用另一个对象来查找某个对象,它也被称为“关联数组”,因为它将某些对象与另外一些对象关联在了一起;或者被称为“字典”,因为你可以使用键对象来查找值对象,就像在字典中使用单词来定义一样。
Map 提供了一个从键映射到值的数据结构,它用于保存键值对。其中值可以重复,但键是唯一的。Java 类库中有多个实现该接口的类:HashMap、TreeMap、LinkedHashMap、WeakHashMap 和 IdentityHashMap。虽然他们都实现了相同的接口,但执行效率却不是完全相同的。
HashMap 是基于散列表实现的,采用对象的 hashCode 可以进行快速查询;
HashMap 没有按照任何明显的顺序来保存其元素。LinkedHashMap 采用列表来维护内部的顺序;
LinkedHashMap 按照插入顺序保存键,同时还保留了 HashMap 的查询速度。- TreeMap 基于红黑树的数据结构来实现的,内部元素是按序排列的;
TreeMap 按照比较结果的升序保存键。
Map 中 put() 和 get() 方法的说明:
Map.put(key, value) 方法将增加一个值(你想要增加的对象),并将它与某个键(你用来查找这个值的对象)关联起来。
Map.get(key) 方法将产生与这个键相关联的值。
下面来看几个示例。
示例:1:
考虑一个程序,它将用来检查 Java 的 Random 类的随机性。 理想状态下,Random 可以将产生理想的数字分布,但要测试它,则需要生成大量的随机数,并对落入各种不同范围的数字进行计数。Map 可以很容易地解决该问题。
在本例中,键是由 Random 产生的数字,而值是该数字出现的次数。
import java.util.*;
import mypackage.Print;
public class Statistics {
public static void main(String[] args) {
Random rand = new Random(47);
Map<Integer, Integer> m = new HashMap<Integer, Integer>();
for(int i = 0; i < 10000; i++) {
int r = rand.nextInt(20);
Integer freq = m.get(r);
m.put(r, freq == null ? 1 : freq +1);
}
System.out.println(m);
}
}/* Output:
{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, 7=471, 8=468, 9=549, 10=513,
11=531, 12=521, 13=506, 14=477, 15=497, 17=509, 16=533, 19=464, 18=478}
*///~
自动包装机制将随机生成的 int 转换为 HashMap 可以使用的 Integer 引用。
如果键不在容器中,get() 方法将返回 null(这表示该数字地已被找到),否则,get() 方法将产生与该键相关联的 Integer 值,然后这个值被递增。
示例2:
使用 containsKey() 和 containsValue() 来查看一个 Map 是否包含某个键或某个值。
下面的示例允许你使用 String 描述来查找 Pet,它还展示了你可以使用怎样的方法通过使用 containsKey() 和 containsValue() 来测试一个 Map,以便查看它是否包含某个键或某个值。
import java.util.*;
import typeinfo.pets.*;
import static mypackage.Print.*;
public class PetMap {
public static void main(String[] args) {
Map<String, Pet> petMap = new HashMap<String, Pet>();
petMap.put("My Cat", new Cat("Molly"));
petMap.put("My Dog", new Dog("Ginger"));
petMap.put("My Hamster", new Hamster("Bosco"));
print(petMap);
Pet dog = petMap.get("My Dog");
print(dog);
print(petMap.containsKey("My Dog"));
print(petMap.containsValue(dog));
print(petMap.values());
}
}/* Output:
{My Cat=Cat Molly, My Dog=Dog Ginger, My Hamster=Hamster Bosco}
Dog Ginger
true
true
[Cat Molly, Dog Ginger, Hamster Bosco]
*///~
示例3:
Map 与数组和其他 Collection 一样,可以很容易地扩展到多维,而我们只需将其值设置为Map(这些Map的值可以是其它容器,甚至是其他Map)。因此,我们能够很容易地将容器组合起来从而快速的生成强大的数据结构。
例如,假如你正在跟踪拥有多个宠物的人,你所需只是一个 Map
import typeinfo.pets.*;
import java.util.*;
import static mypackage.Print.*;
public class MapOfList {
public static Map<Person, List<? extends Pet>>
petPeople = new HashMap<Person, List<? extends Pet>>();
static {
petPeople.put(new Person("Dawn"),
Arrays.asList(new Cymric("Molly"),
new Mutt("Spot")));
petPeople.put(new Person("Kate"),
Arrays.asList(new Cat("Shackleton"),
new Cat("Elsie May"),
new Dog("Margrett")));
petPeople.put(new Person("Marilyn"),
Arrays.asList(
new Pug("Louie aka Louis Snorkelstein Dupree"),
new Cat("Stanford aka Stinky el Negro"),
new Cat("Pinkola")));
petPeople.put(new Person("Luke"),
Arrays.asList(new Rat("Fuzzy"),
new Rat("Fizzy")));
petPeople.put(new Person("Isaac"),
Arrays.asList(new Rat("Freckly")));
}
public static void main(String[] args) {
print("People: " + petPeople.keySet());
print("Pets: " + petPeople.values());
for(Person person : petPeople.keySet()) {
print(person + " has:");
for(Pet pet : petPeople.get(person))
print(" " + pet);
}
}
}/* Output:
People: [Person Marilyn, Person Luke, Person Isaac, Person Kate, Person Dawn]
Pets: [[Pug Louie aka Louis Snorkelstein Dupree, Cat Stanford aka Stinky el Negro, Cat Pinkola],
[Rat Fuzzy, Rat Fizzy], [Rat Freckly], [Cat Shackleton, Cat Elsie May, Dog Margrett],
Cymric Molly, Mutt Spot]]
Person Marilyn has:
Pug Louie aka Louis Snorkelstein Dupree
Cat Stanford aka Stinky el Negro
Cat Pinkola
Person Luke has:
Rat Fuzzy
Rat Fizzy
Person Isaac has:
Rat Freckly
Person Kate has:
Cat Shackleton
Cat Elsie May
Dog Margrett
Person Dawn has:
Cymric Molly
Mutt Spot
*///~
Map 可以返回它的键的 Set,它的值的 Collection,或者它的键值对的 Set。
KeySet() 方法产生了由在 petPeople 中的所有键组成的 Set,它在 foreach 语句中被用来迭代遍历该 Map。