1.Map集合
1.1Map集合概述和特点
Map集合概述
interface Map<K,V> K:键的类型;V:值的类型
Map集合的特点
双列集合,一个键对应一个值
键不可以重复,值可以重复
Map集合的基本使用
public class MapDemo01 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//V put(K key, V value) 将指定的值与该映射中的指定键相关联
map.put("itheima001","林青霞");
map.put("itheima002","张曼玉");
map.put("itheima003","王祖贤");
map.put("itheima003","柳岩");
//输出集合对象
System.out.println(map);
}
}
发现有二个itheima003,之前说过键和值是一 一对应关系,且键不可以重复,值可以重复
itheima003(键)重复了,所以没有打印出来,从上到下覆盖
1.2Map集合的基本功能
方法介绍
方法名 说明 V put(K key,V value) 添加元素 V remove(Object key) 根据键删除键值对元素 void clear() 移除所有的键值对元素 boolean containsKey(Object key) 判断集合是否包含指定的键 boolean containsValue(Object value) 判断集合是否包含指定的值 boolean isEmpty() 判断集合是否为空 int size() 集合的长度,也就是集合中键值对的个数
package Map;
import java.util.HashMap;
import java.util.Map;
/*
put(K key,V value) | 添加元素 |
| remove(Object key) | 根据键删除键值对元素 |
| void clear() | 移除所有的键值对元素 |
| boolean containsKey(Object key) | 判断集合是否包含指定的键 |
| boolean containsValue(Object value) | 判断集合是否包含指定的值 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中键值对的个数 |
*/
public class demo2 {
public static void main(String[] args) {
//创建集合对象
Map<String, String> map = new HashMap<>();
//V put(K key,V value):添加元素
map.put("张无忌", "赵敏");
map.put("郭靖", "黄蓉");
map.put("杨过", "张三");
String value1 = map.put("杨过", "小龙女");
//2.添加元素
//put方法的细节:
//添加/覆盖
//在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null
//在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。
System.out.println(value1);//如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。
String value2 = map.put("王五", "小龙女");
System.out.println(value2);//null 如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null
//删除
boolean result = map.remove("郭靖", "黄蓉");
System.out.println(result);
//清空
//map.clear();
//判断是否包含
boolean keyresult = map.containsKey("郭靖");
System.out.println(keyresult);
boolean valueresult = map.containsValue("小龙女");
System.out.println(valueresult);
int size = map.size();
System.out.println(size);
//3.打印集合
System.out.println(map);
}
}
1.3Map集合的获取功能
方法介绍
方法名 | 说明 |
---|---|
V get(Object key) | 根据键获取值 |
Set<K> keySet() | 获取所有键的集合 |
Collection<V> values() | 获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
方法1(遍历)
把所有的键存储再单列集合里面,然后通过键找到与之对应的值,通过get方法获取值即可
遍历思路
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
把所有的丈夫给集中起来
遍历丈夫的集合,获取到每一个丈夫
根据丈夫去找对应的妻子
步骤分析
获取所有键的集合。用keySet()方法实现
遍历键的集合,获取到每一个键。用增强for实现
根据键去找值。用get(Object key)方法实现
package Map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class demo3 {
public static void main(String[] args) {
//map的第一种遍历方式
//1.创建map集合对象
Map<String, String> map = new HashMap<>();
map.put("张无忌", "赵敏");
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
//2.通过键找值
//2.1 获取所有的键,把这些键放入单列集合当中
Set<String> keySet = map.keySet();
//2.2遍历单列集合,得到每一个键;
for (String s : keySet) {
//System.out.println(s);
//2.3 利用Map集合中的键获取对应的值 Get
String value = map.get(s);
System.out.println(s + "=" + value);
}
}
}
方法2(遍历)
遍历思路
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
获取所有结婚证的集合
遍历结婚证的集合,得到每一个结婚证
根据结婚证获取丈夫和妻子
步骤分析
获取所有键值对对象的集合
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry
根据键值对对象获取键和值
用getKey()得到键
用getValue()得到值
获取getkey方法和getvalue方法
//通过键值对对象进行遍历
//3.1通过一个方法获取所有的键值对对象 ,返回一个Set集合
//获取getkey方法和getvalue方法即可
Set<Map.Entry<String, String>> entries = m.entrySet();
//3.2遍历entries这个集合,去得到里面的每一个键值对对象
第二种方法的lambda表达式
package Map;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class demo4 {
public static void main(String[] args) {
//map的第二种遍历方式
Map<String, String> m = new HashMap<>();
m.put("张无忌", "赵敏");
m.put("郭靖", "黄蓉");
m.put("杨过", "小龙女");
//通过键值对对象进行遍历
//3.1通过一个方法获取所有的键值对对象 ,返回一个Set集合
//获取getkey方法和getvalue方法即可
Set<Map.Entry<String, String>> entries = m.entrySet();
//3.2遍历entries这个集合,去得到里面的每一个键值对对象
//1.增强for
/*for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}*/
//entry 第一次循环的时候代表的是张无忌", "赵敏这个键值对对象,以此类推
//迭代器
/*Iterator<String> it= m.keySet().iterator();
while(it.hasNext()){
String key = it.next();
String value = m.get(key);
System.out.println(key+"="+value);
}*/
//lambda表达式
//方法的底层其实就是利用增强for进行遍历,依次得到每一个键和值
//再调用accept方法
m.forEach(( s1, s2)-> System.out.println(s1+"="+s2));
}
}
2.HashMap集合
2.1HashMap集合概述和特点
HashMap底层是哈希表结构的
依赖hashCode方法和equals方法保证键的唯一
如果键要存储的是自定义对象,需要重写hashCode和equals方法
练习1
package HashMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class demo1 {
public static void main(String[] args) {
HashMap<Student, String> m = new HashMap<>();
Student s1 = new Student("张三", 18);
Student s2 = new Student("李四", 20);
Student s3 = new Student("王五", 19);
m.put(s1, "湖北省");
m.put(s2, "重庆");
m.put(s3, "江苏省");
/* //获取迭代器对象
//迭代器对象好比是一个指针,默认指向集合的0索引处
Iterator<Student> it = m.keySet().iterator();
// 利用循环不断的去获取集合中的每一个元素
while (it.hasNext()) {
//next方法的二件事情:获取指针指向的元素并且移动指针
Student key = it.next();//键
String value = m.get(key);//值
System.out.println(key + "\t" + value);
}*/
/* //增强for方法1
//先获取所有键的对象
Set<Student> keys = m.keySet();//遍历单列集合,得到每一个键;
for (Student key : keys) {
String value = m.get(key);//根据键去找值
System.out.println(key + "\t" + value);
}*/
//增强for方法2
for (Map.Entry<Student, String> entry : m.entrySet()) {//获取所有键值对对象的集合
//遍历键值对对象的集合,得到每一个键值对对象--entry
Student key = entry.getKey();//利用entry对象去获取键
String value = entry.getValue();//利用entry对象去获取值
System.out.println(key + "\t" + value);
}
}
}
因为要求是说的键,键存储的是自定义对象,所以要重写方法
package HashMap;
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
练习2
package HashMap;
import java.util.*;
public class demo2 {
public static void main(String[] args) {
//定义一个数组存储景点
String[] arr = {"A", "B", "C", "D"};
//创建一个集合存储学生投票选择的景点
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 80; i++) {
int index = r.nextInt(arr.length);
//把学生随机投的票存入集合当中
list.add(arr[index]);
}
//利用map集合统计景点次数
HashMap<String, Integer> map = new HashMap<>();
for (String s : list) {
//map集合里面存在学生头的景点
boolean containsKey = map.containsKey(s);
int count = 0;
//判断map集合里面是否包含该景点
if (containsKey) {
//存在count++;
//先获取当前景点已经被投了多少次数
count = map.get(s);
//当前景点又被投了一次
count++;
//把当前景点加新的次数再次添加到map集合当中
map.put(s, count);
} else {
//不存在count为1
map.put(s, 1);
}
}
//求次数最多的景点
int max=0;
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
int count = entry.getValue();
if(count>max){
max=count;
}
System.out.println(key+":"+count);
}
//判断哪个景点的次数跟最大值一样,一样就打印出来
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
int count = entry.getValue();
if(count==max){
System.out.println(key);
}
}
}
}
3.LinkedHashMap集合
package LinkedHashMap;
import java.util.LinkedHashMap;
public class demo1 {
public static void main(String[] args) {
/*
LinkedHashMap:
由键决定:
有序、不重复、无索引。
有序:
保证存储和取出的顺序一致
原理:
底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
*/
LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
lhm.put("c", 001);
lhm.put("b", 002);
lhm.put("a", 001);
System.out.println(lhm);
//存取顺序一致
}
}
4.TreeMap集合
package TreeMap;
import java.util.Set;
import java.util.TreeMap;
public class demo1 {
public static void main(String[] args) {
// 采取第二种排序方式:比较器排序 因为第一种方法是默认升序,所以不能满足需求
//Integer Double 默认情况下都是按照升序排列的
//String 按照字母再ASCII码表中对应的数字升序进行排列
TreeMap<Integer, String> tm1 = new TreeMap<>((o1, o2) -> o1 - o2);
//o1是当前要添加的元素,
//o2表示红黑树中存在的元素
tm1.put(1, "可乐");
tm1.put(3, "雪碧");
tm1.put(2, "红牛");
//要求1 按照id的升序排列;
method01(tm1);
System.out.println("-----------");
//要求2 按照id降序排列
TreeMap<Integer, String> tm2 = new TreeMap<>((o1, o2) -> o2 - o1);
tm2.put(1, "可乐");
tm2.put(3, "雪碧");
tm2.put(2, "红牛");
method01(tm2);
}
private static void method01(TreeMap<Integer, String> tm) {
//获取所有的键,并存入单列集合当中
Set<Integer> keys = tm.keySet();
//遍历单列集合,得到每一个键(id) 升序
for (Integer key : keys) {
String value = tm.get(key);
System.out.println(key+"--"+value);
}
}
}
@Override
public int compareTo(Student o) {
//要求: 按照学生的年龄排序,年龄一样按照姓名和字母排序,同姓名和年龄视为同一个人
//this表示当前要添加的元素
//o表示红黑树存在的元素
//返回值:
//负数: 认为要添加的元素在左边
//正数:认为要添加的元素在右边
//0:认为要添加的元素存在,舍弃
int tmp=this.getAge()-o.getAge();
tmp= tmp==0? this.getName().compareTo(o.getName()):tmp;
return tmp;
}
package TreeMap;
import java.util.TreeMap;
public class demo2 {
public static void main(String[] args) {
Student s1 = new Student("zhangsan", 18);
Student s2 = new Student("lisi", 17);
Student s3 = new Student("wangwu", 20);
TreeMap<Student, String> tm = new TreeMap<>();
tm.put(s1, "湖北省");
tm.put(s3, "广东省");
tm.put(s2, "江苏省");
//要求: 按照学生的年龄排序,年龄一样按照姓名和字母排序,同姓名和年龄视为同一个人
System.out.println(tm);
}
}
package TreeMap;
import java.util.*;
//利用map集合来添加字符出现的次数
/*
新的统计思想,如果题目没有要求对结果排序默认使用HaShMap
如果有排序就使用TreeMap 因为 a(5) b(4) c(3) d(2) e(1)按照Ascll码值排好了
*/
public class demo3 {
public static void main(String[] args) {
String str="aababcabcdabcde";
char[] arr = str.toCharArray();
ArrayList<Character> list = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
list.add(arr[i]);
}
//利用map集合来添加字符出现的次数
TreeMap<Character, Integer> tm = new TreeMap<>();
for (char s : list) {//遍历每一个键
//判断tm集合里面是否存在字符
if (tm.containsKey(s)) {
//存在count++;
int count = 0;
//先获取当前字符已经出现了多少次数
count = tm.get(s);
//当前字符又出现一次
count++;
tm.put(s, count);
} else {
//不存在count为1
tm.put(s, 1);
}
}
Set<Map.Entry<Character, Integer>> entries = tm.entrySet();
for (Map.Entry<Character, Integer> entry : entries) {
char key = entry.getKey();
int value = entry.getValue();
System.out.print(key +"("+ value+")"+" ");
}
}
}
TreeMap<Character, Integer> tm = new TreeMap<>();
for (int i = 0; i < str.length(); i++) {
char s = str.charAt(i);//得到每一个键(字符)
//判断tm集合里面是否存在字符
if (tm.containsKey(s)) {
//存在count++;
int count = 0;
//先获取当前字符已经出现了多少次数
count = tm.get(s);
//当前字符又出现一次
count++;
tm.put(s, count);
} else {
//不存在count为1
tm.put(s, 1);
}
}
什么叫不能满足默认排序规则
如:需要要降序,或者按照字符长度来排序等,这种情况才使用第二种排序规则