Map集合体系详解
Map集合的概述
Map集合概述和使用:
1、Map集合是一种双列集合
,每个元素包含两个数据
。
2、Map集合的每个元素的格式:key=value(键值对元素)
。
3、Map集合也被称为“键值对集合
”。
Map集合整体格式:
Collection集合的格式: [元素1,元素2,元素3..]
Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , ...}
问题Map集合是什么?使用场景是什么样的?
1. Map集合是键值对集合
2. Map集合非常适合做类购物车这样的业务场景。
Map集合体系特点
Map集合体系
Map集合体系特点:
1、Map集合的特点都是由键决定的
。
2、Map集合的键是无序,不重复的,无索引的,值不做要求(可以重复)
。
3、Map集合后面重复的键
对应的值会覆盖前面重复键的值
。
4、Map集合的键值对都可以为null
。
Map集合实现类特点:
1、HashMap
:元素按照键是无序,不重复,无索引,值不做要求。
(与Map体系一致)
2、LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。
3、TreeMap:元素按照建是排序,不重复,无索引的,值不做要求。
Map集合常用API
Map集合 :Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。
Map API如下:
Map API 测试案例:
public class MapDemo {
public static void main(String[] args) {
// 1.添加元素: 无序,不重复,无索引。
Map<String , Integer> maps = new HashMap<>(); // 多态的写法
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",100);// Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
// {huawei=100, 手表=10, 生活用品=10, iphoneX=100, 娃娃=20}
System.out.println(maps);
// 2.清空集合
// maps.clear();
// System.out.println(maps);
// 3.判断集合是否为空,为空返回true ,反之!
System.out.println(maps.isEmpty());
// 4.根据键获取对应值:public V get(Object key)
Integer key = maps.get("huawei");
System.out.println(key);
System.out.println(maps.get("iphoneX"));
System.out.println(maps.get("手表"));
// 5.根据键删除整个元素。(删除键会返回键的值)
maps.remove("huawei");
System.out.println(maps);
// 6.判断是否包含某个键 ,包含返回true ,反之
System.out.println(maps.containsKey("手表")); // true
System.out.println(maps.containsKey("iphoneX")); // true
System.out.println(maps.containsKey("sss")); // false
// 7.判断是否包含某个值。
System.out.println(maps.containsValue(10)); // true
System.out.println(maps.containsValue(100)); // true
System.out.println(maps.containsValue(22)); // false
// 8.获取全部键的集合:public Set<K> keySet()
Set<String> sets = maps.keySet();
System.out.println(sets);
System.out.println("------------------------------");
// 9.获取全部值的集合:Collection<V> values();
Collection<Integer> it = maps.values();
System.out.println(it);
// 10.集合的大小
System.out.println(maps.size());
// 11.合并其他Map集合。(拓展)
Map<String, Integer> map1 = new HashMap<>();
map1.put("Java1", 100);
map1.put("Java2", 200);
Map<String, Integer> map2 = new HashMap<>();
map2.put("Java1", 300);
map2.put("Java3", 400);
map1.putAll(map2);
System.out.println(map1);
System.out.println(map2);
}
}
Map集合的遍历方式一:键找值(推荐)
Map集合的遍历方式一:键找值
1、先获取Map集合的全部键的Set集合。
2、遍历键的Set集合,然后通过键提取对应值。
键找值涉及到的API:
方法名称 | 说明 |
---|---|
Set<\K> keySet() | 获取所有键的集合 |
V get(Object key) | 根据键获取值 |
键找值测试案例1:
Map集合的遍历方式二:键值对当做一个对象一起进行处理(不推荐)
Map集合的遍历方式二:键值对
1、先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了。
2、遍历Set集合,然后提取键以及提取值。
键值对涉及到的API:
方法名称 | 说明 |
---|---|
Set<Map.Enrty<K,V>> entrySet() | 获取所有键值对对象的集合 |
K getKey() | 获取键 |
V getValue() | 获取值 |
键找值测试案例2:
public class MapDemo2 {
public static void main(String[] args) {
Map<String , Integer> maps = new HashMap<>();
// 1.添加元素: 无序,不重复,无索引。
maps.put("娃娃",30);
maps.put("iphoneX",100);
maps.put("huawei",1000);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
// {huawei=1000, 手表=10, 生活用品=10, iphoneX=100, 娃娃=30}
// 1. 把Map集合转换成一个Set集合:Set<Map.Entry<K, V>> entrySet();
Set<Map.Entry<String, Integer>> entries = maps.entrySet();
// 2. 此时键值对元素的类型就确定了,类型是键值对实体类型:Map.Entry<K, V>
// 3. 接下来就可以用foreach遍历这个Set集合,类型用Map.Entry<K, V>
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + "-------->" + entry.getValue());
}
}
}
Map集合的遍历方式三:lambda表达式(推荐)Map集合的遍历方式
Map集合的遍历方式三:Lambda
:得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。
Map结合Lambda遍历的API
键找值测试案例3:
public class MapDemo3 {
public static void main(String[] args) {
// 1.添加元素: 无序,不重复,无索引
Map<String , Integer> maps = new HashMap<>();
maps.put("娃娃",30);
maps.put("iphoneX",100);
maps.put("huawei",1000);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
// 2. 利用lambda表达式访问map集合
// maps.forEach(new BiConsumer<String, Integer>() {
// @Override
// public void accept(String s, Integer integer) {
// System.out.println(s + "----->" + integer);
// }
// });
// 3. 上述部分可以简写为
maps.forEach((s, integer) -> System.out.println(s + "----->" + integer));
}
}
Map集合的实现类HashMap
HashMap的特点
1、HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引
2、没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
3、HashMap跟HashSet底层原理是一模一样的,都是哈希表结构
,只是HashMap的每个元素包含两个值而已。
实际上:Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
1、HashMap的特点和底层原理
1. 由键决定:无序、不重复、无索引。HashMap底层是哈希表结构的。
2. 依赖hashCode方法和equals方法保证键的唯一。
3. 如果键要存储的是自定义对象,需要重写hashCode和equals方法。
4. 基于哈希表。增删改查的性能都较好。
如果想要了解底层原理可以查看文章Java中的Collection集合以及Collection集合实现类实例:https://blog.csdn.net/qq_43751200/article/details/123803851
案例:HashMap集合存储自定义对象并遍历
需求:创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。存储三个键值对元素,并遍历
思路:
1. 定义学生类
2. 创建HashMap集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合
HashMap测试案例:
Map集合的实现类LinkedHashMap
LinkedHashMap集合概述和特点
1、由键决定
:有序、不重复、无索引
。
2、这里的有序
指的是保证存储和取出的元素顺序一致
原理: 底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
如果想要了解底层原理可以查看文章Java中的Collection集合以及Collection集合实现类实例:https://blog.csdn.net/qq_43751200/article/details/123803851
LinkedHashMap测试案例:
Map集合的实现类TreeMap
TreeMap集合概述和特点
1、由键决定特性:不重复、无索引、可排序
2、可排序:按照键数据的大小默认升序(有小到大)排序
。只能对键排序
。
注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序
TreeMap跟TreeSet一样底层原理是一样的。如果想要了解底层原理可以查看文章Java中的Collection集合以及Collection集合实现类实例:https://blog.csdn.net/qq_43751200/article/details/123803851
TreeMap集合自定义排序规则有2种
1、类实现Comparable接口,重写比较规则
。
2、集合自定义Comparator比较器对象,重写比较规则
。
TreeMap测试案例:
public class TreeMapDemo3 {
public static void main(String[] args) {
Map<Integer, String> map = new TreeMap<>();
map.put(14, "王麻子");
map.put(45, "张三");
map.put(32, "赵六");
System.out.println(map);
/**
* TreeSet()底层源码
* public TreeSet() {
* this(new TreeMap<E,Object>());
* }
* new TreeSet<>();
*/
// 1. TreeMap集合自带排序。可排序,不重复, 无索引
// 排序方式二:集合自定义Comparator比较器对象,重写比较规则
Map<Apple, String> maps1 = new TreeMap<>(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return Double.compare(o2.getPrice(), o1.getPrice()); // 按照价格降序
}
});
maps1.put(new Apple("红富士", "红色", 9.9, 500), "山东" );
maps1.put(new Apple("青苹果", "绿色", 15.9, 300), "广州");
maps1.put(new Apple("绿苹果", "青色", 29.9, 400), "江西");
maps1.put(new Apple("黄苹果", "黄色", 9.6, 500), "湖北");
System.out.println(maps1);
// 2.1(推荐) 遍历map集合, 先通过keySet方法获得键,然后遍历键的集合获取值
System.out.println("------------------------------------------------------------------");
Set<Apple> apples = maps1.keySet();
for (Apple apple : apples) {
String value = maps1.get(apple);
System.out.println(apple.toString() + "--->" + value);
}
// 2.2(不推荐) 遍历map集合, 通过调用entrySet方法,把集合中的键值对当做为一个整体进行访问
System.out.println("------------------------------------------------------------------");
Set<Map.Entry<Apple, String>> entries = maps1.entrySet();
for (Map.Entry<Apple, String> entry : entries) {
System.out.println(entry.getKey().toString() + "--->" + entry.getValue());
}
// 2.3 lambda遍历集合
System.out.println("------------------------------------------------------------------");
maps1.forEach( (apple, s) -> System.out.println(apple.toString() + "--->" + s));
}
}
集合的嵌套
需求: 某个班级多名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生可以选择多个景点,请统计出最终哪个景点想去的人数最多。
分析
将80个学生选择的数据拿到程序中去,需要记住每个学生选择的情况。
定义Map集合用于存储最终统计的结果。
import java.sql.Array;
import java.util.HashMap;
import java.util.*;
public class MapTest4 {
public static void main(String[] args) {
// 1. 使用一个Map集合进行存储, K为String类型,V为List集合类型,属于集合套集合类型。
Map<String, List<String>> mapData = new HashMap<>();
// 2. 声明学生选择旅游景点的集合
List<String> str1 = new ArrayList<>();
Collections.addAll(str1, "A", "B", "D");
List<String> str2 = new ArrayList<>();
Collections.addAll(str2, "B", "D");
List<String> str3 = new ArrayList<>();
Collections.addAll(str3, "A", "C", "D");
List<String> str4 = new ArrayList<>();
Collections.addAll(str4, "A", "B");
// 3. 添加学生信息到mapData集合中
mapData.put("张艺谋", str1);
mapData.put("李逵", str2);
mapData.put("张明亮", str3);
mapData.put("宋江", str4);
System.out.println(mapData);
// 4. 统计每一个旅游景点想去的人数
Map<String, Integer> map = new HashMap<>();
// 4.1 通过先拿到键然后再对值进行访问
// Set<String> set = mapData.keySet();
// for (String key : set){
// // 根据key的值拿到对应的键值List集合
// List<String> listTemp = mapData.get(key);
//
// // 对得到的List集合进行遍历,拿到旅游地点信息
// for (int i = 0; i < listTemp.size(); i++) {
// String temp = listTemp.get(i);
// if(map.containsKey(temp)){
// map.put(temp, map.get(temp) + 1);
// }else {
// map.put(temp, 1);
// }
// }
// }
// 4.2 直接拿到键值对中的值,对值的集合进行访问
Collection<List<String>> values = mapData.values(); // 得到所有键值对中的值,值得类型为List<String>类型
for (List<String> value : values) { // 每一个value对应一个List<String>集合
for (String s : value) {
if(map.containsKey(s)){
map.put(s, map.get(s)+1);
}else {
map.put(s,1);
}
}
}
System.out.println(map); // {A=3, B=3, C=1, D=3}
}
}