Map 双列集合
Map 的方法总结
关于Map集合的方法概要(具体见代码,map为HashMap的对象):
加入键值对:map.put("键", "值");
删除键值对:map.remove("键");
获取键对应的值:map.get("键")
,返回对应值的类型
是否含指定键:map.containsKey("键");
,返回布尔
是否含指定值:map.containsValue("值");
,返回布尔
遍历:Set<E> set = map.keySet();
把key都取出来放到一个set中,再用增强for循环
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapDemo {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
String v1 = map.put("沉鱼", "东施");
System.out.println(v1);//结果:null,解释:key不重复,返回v1为null
String v2 = map.put("沉鱼", "西施");
System.out.println(v2);//结果:东施,解释:key重复,返回被替换的value
//一般情况下无需接收,所以直接不用写上面四行
System.out.println(map);//{沉鱼=西施}
map.put("落雁", "王昭君");
map.put("闭月", "貂蝉");
map.put("羞花", "杨玉环");
map.put("杨贵妃", "杨玉环");//体现了键唯一,值可重复。杨玉环可以有多个称号
System.out.println(map);//{杨贵妃=杨玉环, 落雁=王昭君, 闭月=貂蝉, 羞花=杨玉环, 沉鱼=西施}
map.remove("杨贵妃");
//key存在,返回键对应的值;ket不存在,返回null;
//为防止空指针异常,返回值用包装类,而不是基本数据类型
//比如值为int,则写 Integer v1=map.remove();
System.out.println(map);//{落雁=王昭君, 闭月=貂蝉, 羞花=杨玉环, 沉鱼=西施}
String v3 = map.get("闭月");
System.out.println(v3);//貂蝉
String v4 = map.get("萝莉");
System.out.println(v4);//null,解释:没有对应键返回null
boolean b1 = map.containsKey("沉鱼");
System.out.println(b1);//true
boolean b2 = map.containsValue("甄宓");
System.out.println(b2);//false
//遍历
Set<String> set = map.keySet();//把key都取出来放到一个set中
//方法1,迭代器
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String keyy = it.next();
String valuee = map.get(keyy);
System.out.println(keyy + " 键对应的值为:" + valuee);
}
//方法2,增强for
for (String s : set) {
System.out.println(s + " 键对应的值为:" + map.get(s));
}
/*结果相同:
落雁 键对应的值为:王昭君
闭月 键对应的值为:貂蝉
羞花 键对应的值为:杨玉环
沉鱼 键对应的值为:西施
如果不事先把key都取出来放到set中,可以像下面这样写:
*/
for (String s : map.keySet()) {
System.out.println(s + " 键对应的值为:" + map.get(s));
}
}
}
Collection 和 Map 框架的对比
java集合是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。Java集合工具包位置是java.util
java集合主要可以分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)。
里面的难点/主干内容为集合类的两个派生类,Collection 和 Map。简单的说区别就是Collection是单列集合(比如一个ArrayList存放一堆不相关的数据),而Map是双列集合(存放键值对)。前面已经介绍过Collection接口的家族关系关系如下:
本文主要介绍Map接口的家族关系:
可以和Collection类似地去理解:
Map
集合是键值对(双列集合),其中键不允许重复;
HashMap
集合底层是哈希表,因此查询很快(JDK1.8前是数组+单向链表,JDK1.8前是数组+单向链表/红黑树,当链表长度超过8用红黑树,进一步提速),无序,存取顺序可能不一致;
LinkedHashMap
底层是哈希表+链表(这个链表用于记录迭代顺序),有序,存取顺序一致。
Collection 和 Map 框架的联系
为了体现联系,简单地见下面的整体框图,稍有些庞大,具体内容在之后说明:
使用Entry键值对对象遍历Map
遍历Map也可以用Entry键值对对象,其提供了两个方法entry.getKey();
和entry.getValue();
,仍旧在上面的例子中演示:
Set<Map.Entry<String,String>> set2=map.entrySet();
Iterator<Map.Entry<String,String>> it2=set2.iterator();
while(it2.hasNext()){
Map.Entry<String,String> entry=it2.next();
String keyyy=entry.getKey();
String valuee=entry.getValue();
System.out.println(keyyy+":"+valuee);
}
//同样也是增强for顺眼一些
for (Map.Entry<String, String> entry : set2) {
String keyyy=entry.getKey();
String valuee=entry.getValue();
System.out.println(keyyy+":"+valuee);
}
/*结果一致:
落雁:王昭君
闭月:貂蝉
羞花:杨玉环
沉鱼:西施
*/
无论是第一个代码块中的方法,还是第二个代码块中用Entry键值对对象。都体现的是Map不能直接用迭代器或是foreach遍历,都需要转成Set再遍历,前者是把键都单独拿出来组成Set,后者是把键值对对象组成Set。
类 Hashtable 是老古董
最早期的双列集合,是同步的。JDK1.0开始,其他的基本是JDK1.2以后出现的。底层也是一个哈希表,是一个线程安全的集合,速度慢。Hashtable<K,V>的特点是不能存储null值、null键。和Vector一样在JDK1.2以后被更好的集合取代了。但它的一个子类Properties依然在用,Properties集合是当下唯一和IO流相结合的集合。
练习:统计字符个数
map小练习
import java.util.HashMap;
import java.util.Scanner;
public class MapLianXi {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = sc.next();
HashMap<Character, Integer> map = new HashMap<>();
for (char c : str.toCharArray()) {
if (map.containsKey(c)) {
Integer value = map.get(c);
value++;//有就加1再放回去
map.put(c, value);
} else {
map.put(c, 1);//没有就算第一个
}
}
for (Character key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key + ":" + value);
}//展示方法1:遍历输出
System.out.println(map);//展示方法2:直接把整个map输出更方便
}
}
/*
请输入一个字符串:
abcaacbbbbbbbbbb
a:3
b:11
c:2
{a=3, b=11, c=2}
*/