集合(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异常。