集合之Map
目录
Map集合体系
Map集合的概述
- Map集合是一种双列集合,每个元素包含两个数据
- Map集合的每个元素的格式: key = value (键值对元素)。
- Map集合也被称为 ”键值对集合“。
Map集合整体格式
- Collection集合的格式:[元素1,元素2,元素3..]
- Map集合的完整格式:
Map集合使用场景之一:购物车系统
分析:
- 购物车提供的四个商品和购买的数量在后台需要容器存储。
- 每个商品对象都一一对应一个购买数量。
- 把商品对象看成是Map集合的键,购买数量看成Map集合的值。
Map集合体系特点
Map集合体系
说明
- 使用最多的Map集合是HashMap
Map集合体系特点
- Map集合的特点都是由键决定的
- Map集合的键是无序的,不重复的,无索引的,值不做要求(可以重复)
- Map集合后面重复的键对应的值会覆盖前面重复键的值
- Map集合的键值对都可以为null
Map集合实现类特点
- HashMap:元素按照键是无序,不重复,无索引,值不做要求。(与Map体系一致)
- LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求
- TreeMap:元素按照键是排序,不重复,无索引的,值不做要求。
Map集合常用API
Map集合
- Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。
Map API如下:
方法名称 | 说明 |
---|---|
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
Map集合的遍历方式一:键找值
- 先获取Map集合的全部键的Set集合
- 遍历键的Set集合,然后通过键提取对应值
相关API:
方法名称 | 说明 |
---|---|
Set |
获取所有键的集合 |
V get(Object key) | 根据键获取值 |
public class MapDemo01 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("老大",30);
maps.put("iphone",100);
maps.put("huawei",1000);
maps.put("零食",10);
maps.put("手表",10);
System.out.println(maps);
//{huawei=1000, 手表=10, 老大=30, 零食=10, iphone=100}
//1.键找值:第一步,先拿到集合的所有键
Set<String> keys = maps.keySet();
//2.遍历每个键,得到值
for (String key : keys) {
int value = maps.get(key);
System.out.println(key+"===>"+value);
}
}
}
output:
{huawei=1000, 手表=10, 老大=30, 零食=10, iphone=100}
huawei===>1000
手表===>10
老大===>30
零食===>10
iphone===>100
Map集合的遍历方式二:键值对
- 先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了
- 遍历Set集合,然后提取键以及提取值
相关API:
方法名称 | 说明 |
---|---|
Set<Map.Entry<K,V> entrySet() | 获取所有键值对对象的集合 |
K getKey() | 获得键 |
V getValue() | 获取值 |
public class MapDemo01 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("老大",30);
maps.put("iphone",100);
maps.put("huawei",1000);
maps.put("零食",10);
maps.put("手表",10);
System.out.println(maps);
//{huawei=1000, 手表=10, 老大=30, 零食=10, iphone=100}
/**
使用forEach遍历map集合,发现Map集合的键值对元素是没有类型的,所以不可以直接使用forEach遍历集合
可以通过调用Map的方法 entrySet把Map的集合转换成Set集合形式
*/
//1.把Map集合转换成Set集合
Set<Map.Entry<String,Integer>> entries = maps.entrySet();
//2.开始遍历
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key+"====>"+value);
}
}
}
output:
{huawei=1000, 手表=10, 老大=30, 零食=10, iphone=100}
huawei====>1000
手表====>10
老大====>30
零食====>10
iphone====>100
Map集合的遍历方式三:Lambda表达式
相关API
方法名称 | 说明 |
---|---|
default void forEach(BigConsumer<? super K, ? super V> action) | 结合Lambda遍历Map集合 |
public class MapDemo01 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("老大",30);
maps.put("iphone",100);
maps.put("huawei",1000);
maps.put("零食",10);
maps.put("手表",10);
System.out.println(maps);
//{huawei=1000, 手表=10, 老大=30, 零食=10, iphone=100}
// maps.forEach(new BiConsumer<String, Integer>() {
// @Override
// public void accept(String key, Integer value) {
// System.out.println(key+"-->"+value);
// }
// });
maps.forEach(( key, value)-> System.out.println(key+"-->"+value));
}
}
output:
{huawei=1000, 手表=10, 老大=30, 零食=10, iphone=100}
huawei-->1000
手表-->10
老大-->30
零食-->10
iphone-->100
Map集合案例:统计投票人数
需求:
某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多
分析:
- 将80 个学生选择的数据拿到程序中去
- 定义Map集合用于存储最终统计的结果
- 遍历80个学生选择的数据,看Map集合中是否存在,不存在存入'数据=1',存在则对应值+1
public class MapTest1 {
public static void main(String[] args) {
//1.把80个学生选择的数据拿进来
String[] selects = {"A", "B", "C", "D"};
StringBuilder sb = new StringBuilder();
Random r = new Random();
for (int i = 0; i < 80; i++) {
sb.append(selects[r.nextInt(selects.length)]);
}
System.out.println(sb);
//2.定义一个Map集合记录最终统计的结果 A=30,B=、、、
Map<Character, Integer> infos = new HashMap<>();
//3.遍历88个学生选择的数据
for (int i = 0; i < sb.length(); i++) {
//4.提取当前选择景点字符
char ch = sb.charAt(i);
//5.判断集合中是否存在这个键
if (infos.containsKey(ch)) {
//让其值+1
infos.put(ch, infos.get(ch) + 1);
}else {
//说明景点是第一次被选
infos.put(ch,1);
}
}
System.out.println(infos);
}
}
output:
CBAADDBCDDAAABDBCADABDACDDBBBAADADCADDCCBBBDCACCDDDACAADBABCBDAABCBADCDBACBADDAD
{A=23, B=18, C=15, D=24}
Map集合的实现类HashMap
- HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引
- HashMap与HashSet底层原理是一模一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已
- 依赖hashCode方法和equals方法保证键的唯一。
- 如果键要存储的是自定义对象,需要重写hashCode()和equals方法
- 基于哈希表,增删改查性能都较好
实际上:Set系列集合的底层就是Map实现的,只是Set集合的元素只要键数据,不要值数据而已
Map集合的实现类LinkedHashMap
- 由键决定:有序、不重复、无索引
- 这里的有序指的是保证存储和取出的元素顺序是一致的
- 原理:底层数据结构依然是哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序
Map集合的实现类TreeMap
- 由键决定特性:不重复、无索引、可排序
- 可排序:按照键数据的大小默认升序 (由小到大)排序,只能对键排序
- 注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按指定的规则进行排序
TreeMap集合自定义排序的规则有2种
- 类实现Comparable接口,重写比较规则
- 集合自定义Comparator比较器对象,重写比较规则、