Map集合体系
Map集合的概述
Map集合概述和使用:
1.Map集合是一种双列集合,每个元素包含两个数据。
2.Map集合的每个元素的格式:key=value(键值对元素)。
3.Map集合也被称为“键值对集合”。
Map集合整体格式:
1.Collection集合的格式:[元素1,元素2,元素3…]
2.Map集合的完整格式:{key1 = value1,key2 = vakue2,key3 = value3, …}
Map集合的使用场景之一:购物车系统
分析:
1.购物车提供的四个商品和购买的数量在后台需要容器存储。
2.每个商品对象看成是Map集合的键,购买数量看成Map集合的值。
{商品1=2,商品2=3,商品3=2}
Map集合体系特点
1.Map集合的特点都是由键决定的。
2.Map集合的键是无序、不重复的,值不做要求可以重复。
3.Map集合后面重复的键对应的值会覆盖前面重复键的值。
4.Map集合的键值对都可以为null。
Map集合实现类特点:
1.HashMap:元素按照键是无序,不重复,无索引,值不做要求。(与Map体系一致)。
2.LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求。
3.TreeMap:元素按照键是排序,不重复,无索引的,值不做要求。
package d5_Map;
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
// 创建一个Map集合对象
Map<String,Integer> maps = new HashMap <>();
maps.put("Java", 1);
maps.put("mysql", 2);
maps.put("python", 3);
maps.put("Java", 10);
System.out.println(maps); // {Java=10, python=3, mysql=2}
}
}
Map集合常用API
Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。
Map API如下:
package d5_Map;
import java.util.*;
public class MapDemo {
public static void main(String[] args) {
// 创建一个Map集合对象
Map<String,Integer> maps = new HashMap <>();
maps.put("Java", 10);
maps.put("mysql", 20);
maps.put("Java", 100);
maps.put("python", 100);
maps.put("HTML", 10);
maps.put("CSS", 10);
System.out.println(maps); //{Java=100, python=100, CSS=10, mysql=20, HTML=10}
// 清空集合
// maps.clear();
// System.out.println(maps); // {}
// 判断集合是否为空,为空返回true,反之
System.out.println(maps.isEmpty()); // false
// 根据键获取对应值:
Integer key = maps.get("Java");
System.out.println(key); //100
System.out.println(maps.get("js")); //null
// 根据键删除整个元素
maps.remove("CSS");
System.out.println(maps); //{Java=100, python=100, mysql=20, HTML=10}
// 判断是否包含某个键
System.out.println(maps.containsKey("HTML")); //true
// 判断是否包含某个值
System.out.println(maps.containsValue(100)); //true
// 获取所有的键
Set keys = maps.keySet();
System.out.println(keys); // [Java, python, mysql, HTML]
// 获取全部值集合
Collection<Integer> values = maps.values();
System.out.println(values); // [100, 100, 20, 10]
// 集合的大小
System.out.println(maps.size()); // 4
// 合并集合
Map<String,Integer> map1 = new HashMap <>();
map1.put("java1", 1);
map1.put("java2", 2);
System.out.println("map1集合:"+map1); // {java2=2, java1=1}
Map<String,Integer> map2 = new HashMap <>();
map2.put("java3", 3);
map2.put("java4", 4);
System.out.println("map2集合:"+map2); // {java4=4, java3=3}
// 集合合并
map1.putAll(map2);
System.out.println("合并后的map1:"+map1); // {java4=4, java3=3, java2=2, java1=1}
}
}
Map集合的遍历方式:
方式一:键找值的方式遍历,先获取Map集合全部的键,再根据遍历键找值。
方式二:键值对的方式遍历,把"键值对"看成一个整体,难度较大。
方式三:JDK1.8开始之后的新技术:Lambda表达式。
方式一:键找值
1.先获取Map集合的全部键的Set集合。
2.遍历键的Set集合,然后通过键提取对应值。
用到的API:
package d5_Map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo1 {
public static void main(String[] args) {
// 创建一个Map集合对象
Map <String,Integer> maps = new HashMap <>();
maps.put("Java", 10);
maps.put("mysql", 20);
maps.put("python", 100);
maps.put("HTML", 10);
maps.put("CSS", 10);
System.out.println(maps);
// 键找值,第一步,获取集合的全部键
Set<String> keys = maps.keySet();
// 遍历每个键,提取每个值
for (String key : keys) {
int value = maps.get(key);
System.out.println(key+"="+value);
}
}
}
方式二:键值对
1.先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了。
2.遍历Set集合,然后提取以及提取值。
键值对涉及到的API:
package d5_Map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo1 {
public static void main(String[] args) {
// 创建一个Map集合对象
Map <String,Integer> maps = new HashMap <>();
maps.put("Java", 10);
maps.put("mysql", 20);
maps.put("python", 100);
maps.put("HTML", 10);
maps.put("CSS", 10);
System.out.println(maps);
// 键值对:把Map集合转化成Set集合,封装成键值对类型
Set<Map.Entry<String,Integer>> entries = maps.entrySet();
// 开始遍历
for(Map.Entry<String,Integer> entry : entries){
String key = entry.getKey();
int valus = entry.getValue();
System.out.println(key+"="+valus);
}
}
}
方式三:lambda表达式
得益于JDK8开始的新技术Lambda表达式,提供了一种更简单,更直接的遍历集合的方式。
Map结合Lambda遍历的API:
package d5_Map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class MapDemo1 {
public static void main(String[] args) {
// 创建一个Map集合对象
Map <String,Integer> maps = new HashMap <>();
maps.put("Java", 10);
maps.put("mysql", 20);
maps.put("python", 100);
maps.put("HTML", 10);
maps.put("CSS", 10);
System.out.println(maps);
// lambda表达式:
maps.forEach(new BiConsumer <String, Integer>() {
@Override
public void accept(String key, Integer value) {
System.out.println(key+"="+value);
}
});
// 简化:
maps.forEach((String key, Integer value)-> System.out.println(key+"="+value));
}
}
案例:Map集合统计投票人数
需求:
某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A,B,C,D),每个学生只能选择一个景点,请统计出最终那个景点想去的人数最多。
分析:
1.将80个学生选择的数据拿到程序中去。
2.定义Map集合用于存储最终统计的结果。
3.遍历80个学生选择的数据,看Map集合中是否存在,不存在存入“数据=1”,存在则其对应值+1。
package d8_maptest;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class MapTest {
public static void main(String[] args) {
// 把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);
// 定义集合记录最终统计的结果
Map<Character,Integer> infos = new HashMap <>();
// 遍历80个学生选择数据
for (int i = 0; i < sb.length(); i++) {
// 提取当前字符串
char ch = sb.charAt(i);
// 判断map集合中饭是否存在这个键
if(infos.containsKey(ch)){
// 让其+1
infos.put(ch, infos.get(ch)+1);
}else {
// 第一次先放进去
infos.put(ch, 1);
}
}
// 输出map集合
System.out.println(infos);
}
}
Map集合的实现类HashMap
使用最多的Map集合是HashMap。
HashMap的特点:
1.HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引。
2.没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
3.HashMap跟HashSet底层原理是一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已。
实际上:Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
HashMap的添加规则:
HashMap的特点和底层原理:
1.由键决定:无序、不重复、无索引。HashMap底层是哈希表结构的。
2.依赖hashCode方法和equals方法保证键的唯一。
3.基于哈希表。增删改查的性能都比较好。
package d9_map_impl;
import com_collection_set.Student;
import java.util.HashMap;
import java.util.Map;
public class HashMapDemol {
public static void main(String[] args) {
// Map集合是根据键去除重复元素
Map <Student,String> maps = new HashMap <>();
Student s = new Student("snow",20,'男');
Student s1 = new Student("snow",20,'男');
Student s2 = new Student("dream",23,'男');
maps.put(s,"广州");
maps.put(s1,"北京");
maps.put(s2,"上海");
System.out.println(maps);
}
}
LinkeHashMap集合概述和特点:
1.由键决定:有序、不重复、无索引。
2.这里的有序指的是保证存储和取出的元素顺序一致。
原理:底层数据结构依然是哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
package d9_map_impl;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDem {
public static void main(String[] args) {
// 创建一个Map集合对象
Map <String,Integer> maps = new LinkedHashMap <>();
maps.put("Java", 10);
maps.put("mysql", 20);
maps.put("python", 100);
maps.put("HTML", 10);
maps.put("CSS", 10);
System.out.println(maps);
}
}
Map集合的实现类TreeMap
TreeMap集合概念和特点:
1.由键决定特性:不重复、无索引、可排序
2.可排序:按照键数据的大小默认升序(有小到大)排序,只能对键排序。
3.TreeMap跟TreeSet一样底层原理是一样的。
注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序。
TreeMap集合自定义排序规则有2种
1.类实现Comparable接口,重写比较规则。
2.集合自定义Comparator比较器对象,重写比较规则。
TreeMapDemo.java实现类
package d9_map_impl;
import com_collection_set.Apple;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
Map<Integer,String> maps1 = new TreeMap <>();
maps1.put(13, "王麻子");
maps1.put(1, "张三");
maps1.put(3, "李四");
System.out.println(maps1);
// TreeMap集合自带排序,可持续,不重复(只要大小规则认为重复),无索引
Map<Apple,String> maps2 = new TreeMap <>();
maps2.put(new Apple("红富士","红色",9.9,500),"四川");
maps2.put(new Apple("青苹果","绿色",15.9,300),"广东");
maps2.put(new Apple("绿苹果","青色",29.9,400),"江西");
maps2.put(new Apple("黄苹果","黄色",9.8,500),"湖北");
System.out.println(maps2);
// 自定义比较规则
Map<Apple,String> maps3 = new TreeMap <>(new Comparator <Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return Double.compare(o2.getPrice(), o1.getPrice()); // 按照价格排序!
}
});
maps3.put(new Apple("红富士","红色",9.9,500),"四川");
maps3.put(new Apple("青苹果","绿色",15.9,300),"广东");
maps3.put(new Apple("绿苹果","青色",29.9,400),"江西");
maps3.put(new Apple("黄苹果","黄色",9.8,500),"湖北");
System.out.println(maps3);
}
}
Apple.java苹果类
package com_collection_set;
public class Apple implements Comparable<Apple>{
private String name;
private String color;
private double price;
private int weight;
public Apple() {
}
public Apple(String name, String color, double price, int weight) {
this.name = name;
this.color = color;
this.price = price;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Apple{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
", price=" + price +
", weight=" + weight +
'}';
}
/**
* 1.类自定义比较规则
* @param o
* @return
*/
@Override
public int compareTo(Apple o) {
// 按照重量比较,会过滤重复重量
return this.weight - o.weight;
// 不会过滤重复重复重量
// return this.weight - o.weight >= 0?1:-1;
}
}
Map集合实现类特点:
1.HashMap:元素按照键是无序,不重复,无索引,值不做要求,基于哈希表(与Map体系一致)。
2.LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求,基于哈希表。
3.TreeMap:元素只能按照键排序,不重复,无索引的,值不做要求,可以做排序。
集合嵌套
案例:Map集合案例-统计投票人数
需求:
某个班级多名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生可以选择多个景点,请统计出最终那个景点想去的人数最多。
分析:
将80个学生选择的数据拿到程序中去,需要记住每个学生的选择情况。
定义Map集合用于存储最终统计的结果 。
package d9_map_impl;
import java.util.*;
public class MapTest {
public static void main(String[] args) {
// 记录每个学生选择的情况
// 使用一个Map集合存储
Map <String, List<String>> data = new HashMap<>();
// 把学生选择的数据存入进去。
List<String> selects = new ArrayList <>();
Collections.addAll(selects, "A","C");
data.put("snow", selects);
List<String> selects1 = new ArrayList <>();
Collections.addAll(selects1, "A","B","C");
data.put("dream", selects1);
List<String> selects2 = new ArrayList <>();
Collections.addAll(selects2, "A","B","C","D");
data.put("yang", selects2);
System.out.println(data);
// 统计每个景点选择的人数
Map<String,Integer> infos = new HashMap <>();
// 提取所有人选择景点的信息
Collection<List<String>> values= data.values();
for (List <String> value : values) {
for (String s : value) {
// 有没有包含这个景点
if(infos.containsKey(s)){
infos.put(s, infos.get(s) + 1);
}else {
infos.put(s, 1);
}
}
}
System.out.println(infos);
}
}