Map接口
1.概述:
Map集合为映射类型(一一对应的关系),即集合中的每个对象都是成对存在的。映射中存储的每个对象都有一个相应的键(key)对象,在检索时,必须通过相应的键对象来获取值(value)对象,这个操作类似于在字典中查找单词,所以要求键对象必须是唯一的。
2.与Collection的区别:
1.Collection中的集合,元素是孤立存在的(可看作单身汉),向集合中存储元素时采用每次只存储一个元素的方式。
2.Map中的集合,元素是成对存在的(可看作夫妻)。每个元素由键与值两部分组成,通过建可以找到所对应的值。
3.Collection中的集合称为单列集合,Map中的集合称为双列集合。
3.Map接口常用方法:
修饰语和类型 | 方法 | 描述 |
---|---|---|
V | put(K key, V value) | 将指定的值与此映射中的指定键关联 |
V | get(Object key) | 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null |
这里的K指作为键(key)的对象,V指作为值(values)的对象。
注意:这里V put(K key, V value)
方法的返回值为V
,通常情况下,如果打印这个返回值,那么内容都将为null
。但当存储的是重复的键(key)时,不会出现重建现象,而是将原先这个键所对应的值覆盖掉,这时再接收并打印这个返回值时,内容为被覆盖掉的那个值对象。
修饰语和类型 | 方法 | 描述 |
---|---|---|
Set | keySet() | 返回此映射中包含的键的Set视图 |
顾名思义,此方法是将Map集合中的所有键单独存储到一个Set集合中去。由于Map集合中的键值对应关系(就像二次函数中x与y的对应关系),所以得到键后,通过遍历这个Set集合,自然可以得到值。我们可以通过这种方式对Map集合进行遍历。
示例代码:
public class MapDemo1 {
public static void main(String[] args) {
/*
* 1.调用map集合的方法keySet,将所有的键存储到Set集合中
* 2.遍历Set集合,获取出Set集合中的所有元素 (Map中的键)
* 3.调用map集合方法get,通过键获取到值
*/
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
map.put("d", 4);
// 调用map集合的方法keySet,所有的键存储到Set集合中
Set<String> set = map.keySet();
// 遍历Set集合,获取出Set集合中的所有元素 (Map中的键)
Iterator<String> it = set.iterator();
while (it.hasNext()) {
// it.next返回是Set集合元素,也就是Map中的键
// 调用map集合方法get,通过键获取到值
String key = it.next();
Integer value = map.get(key);
System.out.println(key + ":" + value);
}
System.out.println("以增强for的方式遍历:");
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key + ":" + value);
}
}
}
注意:打印集合元素的顺序不按照存储的顺序。
Entry键值对对象:
在Map类设计时,提供了一个静态的内部嵌套接口(相当于内部类):static interface Map.Entry<K,V>
。Entry将键值对的对应关系封装成了对象,即键值对对象。这样我们在遍历Map集合时,就可以从每一个键值对对象(Entry)中获取对象的键与其对应的值。
接口Map.Entry<K,V>方法摘要:
修饰语和类型 | 方法 | 描述 |
---|---|---|
K | getKey() | 返回此项对应的键 |
V | getValue() | 返回此项对应的值 |
Map集合通过entrySet()
方法将集合中的映射关系对象存储到Set集合中:
修饰语和类型 | 方法 | 描述 |
---|---|---|
Set< Map.Entry<K, V> > | entrySet() | 返回此映射中包含的映射关系的Set视图 |
public class MapDemo2 {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "abc");
map.put(2, "bcd");
map.put(3, "cde");
//调用map集合方法entrySet()将集合中的映射关系对象,存储到Set集合
Set<Map.Entry<Integer, String>> set = map.entrySet();
//迭代Set集合
Iterator<Map.Entry<Integer, String>> it = set.iterator();
while (it.hasNext()) {
//获取出的Set集合的元素,是映射关系对象
// it.next 获取的是什么对象,也是Map.Entry对象
Map.Entry<Integer, String> entry = it.next();
// 通过映射关系对象的方法 getKet, getValue获取键值对
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key + ":" + value);
}
//增强for循环方式遍历集合
for(Map.Entry<Integer, String> entry : map.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
注意:
1.Map集合不能直接使用迭代器或者foreach(增强for)进行遍历。但是转成Set之后就可以使用了。
2.获取内部类对象语法:外部类.内部类
。
其他的方法如:remove、size、clear、equals、isEmpty等方法和Collection中的用法差不多,不作赘述。
4.Map集合实现类:
Map集合的实现类有HashMap和LinkedHashMap。
HashMap: 前面的大部分代码已经使用到了hashMap,这里继续再通过示例代码说明一些细节。要求:HashMap存储自定义对象Person
,作为键、值出现。
Person类:
public class Person {
private String name;
private int age;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
@Override
public String toString() {
return "Person" + name + ":" + age ;
}
}
注意:为保证键的唯一性,Person类需要重写hashCode和equals方法,可直接通过Eclipse快捷键Alt + Shift + S
快速自动生成。这里有:Java中hashCode与equals用法。
主函数类:
import java.util.HashMap;
import java.util.Map;
/*
* 使用HashMap集合,存储自定义的对象
* 自定义对象,作为键出现,作为值出现
*/
public class HashMapDemo {
public static void main(String[] args) {
function_1();
function_2();
}
/*
* HashMap 存储自定义对象Person,作为键出现
* 键的对象,是Person类型,值是字符串
* 为保证键的唯一性,Person类重写了hashCode和equals方法。如果不重写,将会出现输出相同键情况。
*/
public static void function_1(){
HashMap<Person, String> map = new HashMap<Person, String>();
map.put(new Person("小王",20), "自贡市");
map.put(new Person("小舒",18), "成都市");
map.put(new Person("小明",18), "长沙市");
map.put(new Person("小李",19), "北京市");
for(Person key : map.keySet()){
String value = map.get(key);
System.out.println(key+":"+value);
}
System.out.println("以增强for遍历输出:");
for(Map.Entry<Person, String> entry : map.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
/*
* HashMap 存储自定义的对象Person,作为值出现
* 键的对象,是字符串,可以保证唯一性
*/
public static void function_2(){
HashMap<String, Person> map = new HashMap<String, Person>();
map.put("自贡市", new Person("小王",20));
map.put("成都市", new Person("小舒",18));
map.put("北京市", new Person("小李",19));
for(String key : map.keySet()){
Person value = map.get(key);
System.out.println(key+":+value);
}
System.out.println("以增强for遍历输出:");
for(Map.Entry<String, Person> entry : map.entrySet()){
String key = entry.getKey();
Person value = entry.getValue();
System.out.println(key+":"+value);
}
}
}
LinkedHashMap: LinkedHashMap继承自HashMap类。它唯一的特点就是:保证了迭代的顺序。
Hashtable: Hashtable依旧是基于哈希表的集合,它和HashMap的用法是一样的。那它有什么独特之处呢?
特点:
1.Hashtable是线程安全集合,运行速度较慢;而HashMap和之前所讲到的所有集合都是线程不安全集合,运行速度更快。
2.HashMap允许允许存储null键,null值;而Hashtable不允许存储null键,null值
由于Hashtable运行速度较慢的这个弊端,从JDK1.2开始,被更先进的HashMap取代了!但是,它被抛弃了,它有个孩子还活着,它有个子类Properties依然活跃在开发的舞台上。Properties 类可以和IO流共同配合,实现数据的持久性存储,它的用法又同父类Hashtable完全一样。
返回Java中集合类知识目录。
推荐了解:Java中方法的可变参数。