集合(List)可以快速地查找现有的元素。但是,要查看一个元素,需要有要查找元素的精确副本。这不是一种非常通用的查询方式。通常,如果知道某些键的信息,并想要查找与之对应的元素,则可以使用映射表(map)。
Java类库中提供了两个通用的实现:HashMap和TreeMap。它们都实现了Map接口。
散列映射表HashMap对键进行散列,树映射表TreeMap用键的整体顺序对元素进行排序,并将其组织成搜索树。散列或比较函数只能作用于键。与键关联的值不能进行散列或比较。
这两个Map的性能哪个更好呢?与集合一样,散列稍微快一些。如果不需要按照排列顺序访问键,就最好选择散列。
每当往映射表里添加对象时,必须同时提供一个对象的键(key),键是一个字符串,对应的值可以是对象。
@Test
public void HashMapTest() {
HashMap<String, Task> map = new HashMap<String, Task>();
Task task1 = new Task("task1", 1);
Task task2 = new Task("task2", 2);
Task task3 = new Task("task3", 3);
map.put("t1", task1);
map.put("t2", task2);
map.put("t3", task3);
System.out.println(map.get("t1").name);
/**
* output:task1
* */
Task task4 = new Task("task4", 4);
map.put("t1", task4);
System.out.println(map.get("t1").name);
/**
* output:task4
* */
System.out.println(map.get("t5"));
/**
* output:null
* */
// 在map中删除一项。3-1=2。
map.remove("t1");
System.out.println(map.size());
/**
* output:2
* */
}
如上面的代码所见,在put时候将对象放入map,如果对同一个键两次调用put方法,第二个值就会取代第一个值。如果在映射表中没有与给定键对应的信息,get将返回null。
remove方法用于删除给定键对应的元素,size方法用于返回元素表中的元素数量。
集合框架并没有将映射表本身视为一个集合(其他的数据结构框架则将映射表视为pairs的集合,也就是对儿的集合,一对的意思,或者视为用键作为索引的值的集合)。然而,可以获得映射表的视图。视图实现了Collection接口对象。
有三个视图,分别是键集合、值集合和键/值集合:
Set<K> KeySet();
Collection<K> values();
Set<Map.Entry<K,V>> enterSet();
第一个KeySet既不是HashSet也不是TreeSet,而是实现了Set接口的某个其他类的对象。Set接口拓展了Collection接口。因此,可以与使用任何集合一样使用KeySet。
使用keyset的代码如下:
@Test
public void HashMapTest() {
HashMap<String, Task> map = new HashMap<String, Task>();
Task task1 = new Task("task1", 1);
Task task2 = new Task("task2", 2);
Task task3 = new Task("task3", 3);
map.put("t1", task1);
map.put("t2", task2);
map.put("t3", task3);
Set<String> keys = map.keySet();
for(String key : keys)
System.out.println(key);
/**
* output:
* t1,t2,t3
* */
}
如果想要同时查看键与值,就可以通过每句哥哥条目(entries)查看,以避免对值进行查找。可以使用下面这段代码框架:
@Test
public void HashMapTest() {
HashMap<String, Task> map = new HashMap<String, Task>();
Task task1 = new Task("task1", 1);
Task task2 = new Task("task2", 2);
Task task3 = new Task("task3", 3);
map.put("t1", task1);
map.put("t2", task2);
map.put("t3", task3);
for(Map.Entry<String, Task> entry : map.entrySet()) {
String key = entry.getKey();
Task task = entry.getValue();
// 从写了Task类的toString方法。
System.out.println("key = " + key + ", value = " + task.toString() + ";");
}
/**
* output:
* key = t1, value = Task [name=task1, priority=1];
* key = t2, value = Task [name=task2, priority=2];
* key = t3, value = Task [name=task3, priority=3];
* */
}
如果调用迭代器的remove方法,实际上就从映射表中删除了键以及对应的值。但是,不能将元素添加到视图中。如果只添加值是毫无意义的。如果试图调用add方法,将会抛出UnsupportedOperationException异常。