Day18JavaSE——Map集合&Collections工具类&集合案例练习
文章目录
Map集合
概述&特点
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
/*
* 我们生活中还会遇到一类数据
* 键----------值
* 学号-------姓名
* s001------张三
* s002------李四
* s003------王五
* 这种一一对应的关系称为键值对应
* 键是唯一的,同一个键的值可以被覆盖
* */
用List做
public class Test1 {
public static void main(String[] args) {
/*List是链式存储的*/
ArrayList<String> numName = new ArrayList<>();
numName.add("s001------张三");
numName.add("s001------张三");
numName.add("s001------张三");
String s = numName.get(0);
System.out.println(s);
String[] sNumName = s.split("-+");
System.out.println(sNumName[0]);
System.out.println(sNumName[1]);
/*
* 在生活中这种键值对应得数据很常见,Java为了方便对这种数据的操作
* 提供了一个叫做Map的集合
* 专门用来操作这种键值对应的数据
* */
//Map将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值
/*Map接口与Collection忌口的不同
* Map是双列的,Collection是单列的
*
* Map的键是唯一的,Collection的子体系Set是唯一的
*
* Map集合的数据结构针对键有效,跟值无关
* Collection集合的数据结构是针对元素有效的*/
}
}
用Map接口做
public class Test2 {
public static void main(String[] args) {
//Map接口中常用的实现类有HashMap和TreeMap,其中HashMap更加常用
//由于Map是接口,所以需要引入该接口的子类去创建接口对象
//双列集合的数据结构
//Map其实实现的是一种映射的关系,但是与数学中的映射不同
//在Map中,Key是唯一的,而键与值的这种映射关系是一一对应的
//所以值也是一一对应的,不存在一键对应多值的现象
HashMap<String, String> studentNum = new HashMap<>();
//第一次存储一个键值对时,返回的时null
String put = studentNum.put("s001", "小刘");
studentNum.put("s002","小王");
studentNum.put("s003","小慧");
studentNum.put("s004","小王");
studentNum.put("s005","小张");
System.out.println(studentNum);
System.out.println(put);
System.out.println("=============================");
//当键相同时,值被覆盖,且返回的是旧值
String put1 = studentNum.put("s001", "Adair");
System.out.println(studentNum);
System.out.println(put1);
}
}
HashMap
HashMap集合功能
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
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);
}
}
public class Test1 {
public static void main(String[] args) {
//存储键是String类型,值是Student类型
//键唯一
//双列集合的数据结构只跟键有关
//HashMap键的数据结构是哈希表,你要保证键唯一,要求自定义对象重写hashCode和equals方法
//因为创建Map对象的是HashMap,底层实现用的是哈希表,所以存储是无序的
HashMap<String, Student> stringStudentHashMap = new HashMap<>();
stringStudentHashMap.put("s001",new Student("小刘",22));
stringStudentHashMap.put("s002",new Student("小王",23));
stringStudentHashMap.put("s003",new Student("老张",38));
stringStudentHashMap.put("s004",new Student("小天",19));
//在Map中存储的值是唯一的
stringStudentHashMap.put("s001",new Student("小刘",22));
System.out.println(stringStudentHashMap);
// HashSet 底层用的是HashMap存的
// new HashSet<>().add()
System.out.println("=====================================");
//删除一对键值对,返回的是这个键对应的值
Student s003 = stringStudentHashMap.remove("s003");
System.out.println(s003);
System.out.println(stringStudentHashMap);
}
}
public class Test2 {
public static void main(String[] args) {
HashMap<Integer, String> integerStringHashMap = new HashMap<>();
integerStringHashMap.put(85,"小刘");
integerStringHashMap.put(50,"小王");
integerStringHashMap.put(46,"小张");
integerStringHashMap.put(89,"小胡");
integerStringHashMap.put(79,"小天");
integerStringHashMap.put(36,"小点");
integerStringHashMap.put(85,"小刘");
System.out.println(integerStringHashMap);
//判断集合中有没有这个键
boolean b = integerStringHashMap.containsKey(79);
System.out.println(b);
//判断集合中是否有这个值
boolean value = integerStringHashMap.containsValue("小刘");
System.out.println(value);
//获取集合的长度
System.out.println(integerStringHashMap.size());
//清空集合
integerStringHashMap.clear();
//判断集合知否为空
boolean empty = integerStringHashMap.isEmpty();
System.out.println(empty);
}
}
HashMap集合遍历
public class Test3 {
public static void main(String[] args) {
//集合遍历
HashMap<String, Student> stringStudentHashMap = new HashMap<>();
stringStudentHashMap.put("s001",new Student("小刘",22));
stringStudentHashMap.put("s002",new Student("小王",23));
stringStudentHashMap.put("s003",new Student("老张",38));
stringStudentHashMap.put("s004",new Student("小天",19));
System.out.println("============方式1============");
//通过键找值的方式来遍历
//获取所有的键集
Set<String> strings = stringStudentHashMap.keySet();
System.out.println(strings);
//遍历键集
for (String key : strings) {
//键找值
Student student = stringStudentHashMap.get(key);
System.out.println(student);
}
System.out.println("============方式2============");
//获取所有的键值对 对象
/*Set<Map.Entry<K,V>> entrySet()
返回此地图中包含的映射的Set视图。*/
/* K getKey ()
返回对应于此项的键。
V getValue ()
返回对应于此项的值。*/
//将Map里面的数据以对象的形式获取出来
Set<Map.Entry<String, Student>> entries = stringStudentHashMap.entrySet();
//遍历键值对集合
for (Map.Entry<String, Student> node : entries) {
String key = node.getKey();
Student value = node.getValue();
System.out.println(key + "====" + value);
}
System.out.println("============方式3============");
//JDK1.8提供的通过forEach()方法遍历
stringStudentHashMap.forEach(new BiConsumer<String, Student>() {
@Override
public void accept(String s, Student student) {
System.out.println(s + "====" + student);
}
});
}
}
LinkedHashMap
public class Test1 {
public static void main(String[] args) {
//HashMap 键的数据结构是哈希表 保证键唯一,键无序
//LinkedHashMap 键的数据结构链表和哈希表。链表保证了键有序,哈希表保证了键唯一。
LinkedHashMap<Integer, String> integerStringLinkedHashMap = new LinkedHashMap<>();
integerStringLinkedHashMap.put(85,"小刘");
integerStringLinkedHashMap.put(50,"小王");
integerStringLinkedHashMap.put(46,"小张");
integerStringLinkedHashMap.put(89,"小胡");
integerStringLinkedHashMap.put(79,"小天");
integerStringLinkedHashMap.put(36,"小点");
integerStringLinkedHashMap.put(85,"小刘");
//按照存入顺序存储,并不像HashMap那样无序
System.out.println(integerStringLinkedHashMap);
}
}
TreeMap
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
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);
}
}
public class Test1 {
public static void main(String[] args) {
/*A: TreeMap: 键的数据结构是红黑树,可保证键的排序和唯一性
* 排序分为自然排序和比较器排序
* 线程是不安全的效率比较高
* */
//空参构造,就使用的自然排序。
/*自然排序,他对键的要求是,要求键实现Comparable接口
重写 compareTo方法,根据此方法的返回值的正负0 来决定键的排列顺序*/
//Integer 默认实现了Comparable接口
TreeMap<Integer, String> integerStringTreeMap = new TreeMap<>();
integerStringTreeMap.put(85,"小刘");
integerStringTreeMap.put(50,"小王");
integerStringTreeMap.put(46,"小张");
integerStringTreeMap.put(89,"小胡");
integerStringTreeMap.put(79,"小天");
integerStringTreeMap.put(36,"小点");
integerStringTreeMap.put(85,"小刘");
System.out.println(integerStringTreeMap);
System.out.println("=================================");
//TreeSet是单列集合
//TreeMap是双列集合
//调用空参构造即默认使用自然排序
TreeMap<String, Student> stringStudentTreeMap = new TreeMap<>();
stringStudentTreeMap.put("s001",new Student("小刘",22));
stringStudentTreeMap.put("s003",new Student("小王",23));
stringStudentTreeMap.put("s002",new Student("老张",38));
stringStudentTreeMap.put("s004",new Student("小天",19));
System.out.println(stringStudentTreeMap);
}
}
public class Test2 {
public static void main(String[] args) {
//使用比较器排序
TreeMap<Integer, String> integerStringTreeMap = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
integerStringTreeMap.put(85,"小刘");
integerStringTreeMap.put(50,"小王");
integerStringTreeMap.put(46,"小张");
integerStringTreeMap.put(89,"小胡");
integerStringTreeMap.put(79,"小天");
integerStringTreeMap.put(36,"小点");
integerStringTreeMap.put(85,"小刘");
System.out.println(integerStringTreeMap);
System.out.println("=========================");
//使用比较器排序,按照年龄大小
TreeMap<Student, String> stringStudentTreeMap = new TreeMap<Student, String>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int i = o1.getAge() - o2.getAge();
int j = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
return j;
}
});
stringStudentTreeMap.put(new Student("小刘",22),"s001");
stringStudentTreeMap.put(new Student("小王",23),"s003");
stringStudentTreeMap.put(new Student("老张",38),"s002");
stringStudentTreeMap.put(new Student("小天",19),"s004");
System.out.println(stringStudentTreeMap);
}
}
HashMap和Hashtable的区别
public class demo1 {
public static void main(String[] args) {
// HashMap 并允许 null值和 null关键。线程不安全效率高
HashMap<Object, Object> objectHM = new HashMap<>();
objectHM.put(null,"adfasdf");
objectHM.put("asdfas",null);
System.out.println(objectHM);
// Hashtable 不允许存储null值和null键 线程安全效率低
Hashtable<Object, Object> hm = new Hashtable<>();
hm.put(null,"zxcZx");
//上面这句会报错,因为Hashtable不允许存储null
}
}
Collections(集合工具类)
//Java针对 Collection 集合,提供了一个工具类Collections 为了方便的去操作 Collection 集合
/* A:
Collections类概述:
针对集合操作 的工具类
B:
Collections成员方法
public static <T > void sort (List < T > list):排序, 默认按照自然顺序
public static <T > int binarySearch (List < ? > list, T key):二分查找 前提 元素有序
public static <T > T max(Collection < ? > coll):获取最大值
public static <T > T min(Collection < ? > coll):获取最小值
public static void reverse (List < ? > list):反转
public static void shuffle (List < ? > list):随机置换*/
集合练习
练习1(统计字符串中每个字符出现的次数)
/* A:
案例演示:
需求:统计字符串中每个字符出现的次数
"aababcabcdabcde", 获取字符串中每一个字母出现的次数要求结果:a(5) b(4) c(3) d(2) e(1)*/
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一段字符串");
String s = sc.nextLine();
//Character是基本类型char的包装类
HashMap<Character, Integer> charNum = new HashMap<>();
/*for (int i = 0; i < s.length(); i++) {
if(charNum.containsKey(s.charAt(i))){
}else{
charNum.put(s.charAt(i),1);
}
}*/
//将字符串转换成字符并遍历
for (char c : s.toCharArray()) {
if(!charNum.containsKey(c)){
charNum.put(c,1);
}else{
//取出这个键对应的这个值
Integer integer = charNum.get(c);
//这个键的值增加1
integer++;
//键相同,值被覆盖
charNum.put(c,integer);
}
}
//遍历集合输出
//获得键集合,然后遍历Map获取每一个键的值
Set<Character> key = charNum.keySet();
for (Character ch : key) {
System.out.println(ch+"----"+charNum.get(ch));
}
//另一种拼接方式
//用StringBuilder遍历拼接
/*StringBuilder sb = new StringBuilder();
charNum.forEach(new BiConsumer<Character, Integer>() {
@Override
public void accept(Character key, Integer value) {
sb.append(key).append("(").append(value).append(")");
}
});
String s1 = sb.toString();
System.out.println(s1);*/
}
}
练习2(集合嵌套之HashMap嵌套HashMap)
/* 基础班
张三 20
李四 22
就业班
王五 21
赵六 23
*/
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> getBaseStudent = new HashMap<>();
getBaseStudent.put("张三",20);
getBaseStudent.put("李四",22);
System.out.println(getBaseStudent);
HashMap<String, Integer> getJobStudent = new HashMap<>();
getJobStudent.put("王五",21);
getJobStudent.put("赵六",23);
System.out.println(getJobStudent);
HashMap<String, HashMap<String, Integer>> school = new HashMap<>();
school.put("基础班",getBaseStudent);
school.put("就业班",getJobStudent);
System.out.println(school);
}
}
练习3(Map 集合 嵌套List集合)
public class Test {
public static void main(String[] args) {
ArrayList<String> sgyy = new ArrayList<>();
sgyy.add("吕布");
sgyy.add("周瑜");
ArrayList<String> xajh = new ArrayList<>();
xajh.add("令狐冲");
xajh.add("林平之");
ArrayList<String> sdxl = new ArrayList<>();
sdxl.add("郭靖");
sdxl.add("杨过");
HashMap<String, ArrayList<String>> book = new HashMap<>();
book.put("三国演义",sgyy);
book.put("笑傲江湖",xajh);
book.put("神雕侠侣",sdxl);
System.out.println(book);
System.out.println("========================");
Set<Map.Entry<String, ArrayList<String>>> entries = book.entrySet();
for (Map.Entry<String, ArrayList<String>> entry : entries) {
String key = entry.getKey();
System.out.println(key);
ArrayList<String> value = entry.getValue();
for (String s : value) {
System.out.println("\t" + s);
}
System.out.println();
}
}
}
练习4(集合嵌套之ArrayList嵌套HashMap)
/* A:
案例演示
集合嵌套之ArrayList嵌套HashMap
假设ArrayList集合的元素是HashMap。有3个。
每一个HashMap集合的键和值都是字符串。
周瑜-- - 小乔
吕布-- - 貂蝉
郭靖-- - 黄蓉
杨过-- - 小龙女
令狐冲-- - 任盈盈
林平之-- - 岳灵珊*/
public class Test {
public static void main(String[] args) {
HashMap<String, String> sg = new HashMap<>();
sg.put("周瑜","小乔");
sg.put("吕布","貂蝉");
HashMap<String, String> sd = new HashMap<>();
sd.put("郭靖","黄蓉");
sd.put("杨过","小龙女");
HashMap<String, String> xa = new HashMap<>();
xa.put("令狐冲","任盈盈");
xa.put("林平之","岳灵珊");
ArrayList<HashMap<String, String>> book = new ArrayList<>();
book.add(sg);
book.add(sd);
book.add(xa);
//遍历1
for (HashMap<String, String> map : book) {
System.out.println(map);
}
//遍历2
book.forEach(new Consumer<HashMap<String, String>>() {
@Override
public void accept(HashMap<String, String> stringStringHashMap) {
System.out.println(stringStringHashMap);
}
});
//遍历3
for (HashMap<String, String> map : book) {
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"------"+value);
}
System.out.println();
}
}
}
模拟斗地主
普通版
public class Test {
public static void main(String[] args) {
//先得有一副牌
//先创建一个集合充当牌盒
ArrayList<String> pokerBox = new ArrayList<>();
//生成54张牌放进牌盒子
String[] colors = {"♠", "♥", "♦", "♣"};
String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
for (String color : colors) {//花色
for (String num : nums) {//牌号
//concat(String str)
//将指定的字符串连接到该字符串的末尾。
String poker = color.concat(num);
pokerBox.add(poker);
}
}
//手动添加大小王
pokerBox.add("☀");
pokerBox.add("☼");
System.out.println(pokerBox);
//洗牌
/*使用工具类Collections
* static void shuffle(List<?> list, Random rnd)
* 使用指定的随机源随机排列指定的列表。*/
Collections.shuffle(pokerBox);
Collections.shuffle(pokerBox);
Collections.shuffle(pokerBox);
//先创建3个斗地主的人
ArrayList<String> peopleWang = new ArrayList<>();
ArrayList<String> peopleZhang = new ArrayList<>();
ArrayList<String> peopleHu = new ArrayList<>();
//留3张底牌作为抢地主的方法
ArrayList<String> endPoker = new ArrayList<>();
System.out.println("=================发牌================");
/*发牌方式
* 1、一个人数十张发
* 2、传统发牌,一人一张*/
System.out.println("================方式1================");
/*//一人发十张
*//*List<E> subList(int fromIndex, int toIndex)
返回此列表中从索引fromIndex到toIndex之间的元素。含头不含尾 *//*
for (int i = 0; i < 17; i++) {
peopleWang.add(pokerBox.get(i));
}
for (int i = 17; i < 34; i++) {
peopleZhang.add(pokerBox.get(i));
}
for (int i = 34; i < 51; i++) {
peopleHu.add(pokerBox.get(i));
}
for (int i = 51; i < 53; i++) {
endPoker.add(pokerBox.get(i));
}
System.out.println(peopleWang);
System.out.println(peopleZhang);
System.out.println(peopleHu);
System.out.println(endPoker);
// peopleWang = (ArrayList<String>) pokerBox.subList(0, 17);*/
System.out.println("================方式2================");
//一人一张转着发
/*peopleWang 0 3 6 9 -------->对三取余为0 放入peopleWang集合
* peopleZhang 1 4 7 10 -------->对三取余为1 放入peopleZhang集合
* peopleHu 2 5 8 11 -------->对三取余为2 放入peopleHu集合
* */
//遍历集合pokerBox
for (int i = 0; i < pokerBox.size(); i++) {
//先留3张底牌
if (i >= (pokerBox.size() - 3)) {
endPoker.add(pokerBox.get(i));
} else if (i % 3 == 0) {
peopleWang.add(pokerBox.get(i));
} else if (i % 3 == 1) {
peopleZhang.add(pokerBox.get(i));
} else {
peopleHu.add(pokerBox.get(i));
}
}
System.out.println(peopleWang);
System.out.println(peopleZhang);
System.out.println(peopleHu);
System.out.println(endPoker);
System.out.println("==================看牌=================");
lookPoker("牌友王", peopleWang);
lookPoker("牌友张", peopleZhang);
lookPoker("牌友胡", peopleHu);
}
private static void lookPoker(String name, ArrayList<String> list) {
System.out.println(name);
System.out.println(list);
}
}
排序版
public class Test2 {
public static void main(String[] args) {
//采用双列集合做牌盒子
HashMap<Integer, String> pokerBox = new HashMap<>();
//创建一个单列集合作为牌的索引,类似于牌的
ArrayList<Integer> indexs = new ArrayList<>();
String[] colors = {"♠", "♥", "♦", "♣"};
String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
int index=0;
for (String color : colors) {
for (String num : nums) {
pokerBox.put(index,num.concat(color));
indexs.add(index);
//给索引集合放一份牌的编号
index++;
}
}
//手动添加大小王
pokerBox.put(index,"●");
indexs.add(index);
index++;
pokerBox.put(index, "○");
indexs.add(index);
//获取键值作为索引值
//洗牌,因为Collections是Collection的工具类,所以洗的是索引集合
Collections.shuffle(indexs);
Collections.shuffle(indexs);
Collections.shuffle(indexs);
//发牌发的也是索引集合,使用TreeSet集合,可以排序
TreeSet<Integer> peopleWang = new TreeSet<>();
TreeSet<Integer> peopleZhang = new TreeSet<>();
TreeSet<Integer> peopleHu = new TreeSet<>();
//留3张底牌作为抢地主的方法
TreeSet<Integer> endPoker = new TreeSet<>();
for (int i = 0; i < indexs.size(); i++) {
//留三张底牌
if(i>=indexs.size()-3){
endPoker.add(indexs.get(i));
}else if(i%3==0){
peopleWang.add(indexs.get(i));
}else if(i%3==1){
peopleZhang.add(indexs.get(i));
}else{
peopleHu.add(indexs.get(i));
}
}
//看牌
lookPoker("牌友王", peopleWang,pokerBox);
lookPoker("牌友张", peopleZhang,pokerBox);
lookPoker("牌友胡", peopleHu,pokerBox);
}
private static void lookPoker(String name,TreeSet<Integer> list,HashMap<Integer, String> pokerBox){
System.out.println(name);
for (Integer key : list) {
System.out.print(pokerBox.get(key)+"\t");
}
System.out.println();
}
}
dexs.size(); i++) {
//留三张底牌
if(i>=indexs.size()-3){
endPoker.add(indexs.get(i));
}else if(i%30){
peopleWang.add(indexs.get(i));
}else if(i%31){
peopleZhang.add(indexs.get(i));
}else{
peopleHu.add(indexs.get(i));
}
}
//看牌
lookPoker(“牌友王”, peopleWang,pokerBox);
lookPoker(“牌友张”, peopleZhang,pokerBox);
lookPoker(“牌友胡”, peopleHu,pokerBox);
}
private static void lookPoker(String name,TreeSet list,HashMap<Integer, String> pokerBox){
System.out.println(name);
for (Integer key : list) {
System.out.print(pokerBox.get(key)+"\t");
}
System.out.println();
}
}