集合进阶综合案例
一、小案例:自动点名器
1、点名器:简单的随机点名
需求
- 班级里有N个学生,实现随机点名器。
测试类
package com.app.demo32_sets_test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class Test1 {
public static void main(String[] args) {
/*
案例:自动点名器1
需求:
班级里有N个学生,实现随机点名器。
*/
// 1.创建集合,用于存储学生姓名
ArrayList<String> list = new ArrayList<>();
// 2.添加数据到集合中
Collections.addAll(list, "范闲", "令狐冲", "杨过", "杨康", "王重阳", "甄姬", "小乔", "大乔", "袁隆平");
// 3.随机点名
// 方式1:
Random rd = new Random(); // 创建随机数对象
int index = rd.nextInt(list.size()); // 生成一个随机索引
String name = list.get(index); // 随机点一名学生
System.out.println("随机点到了" + name + "同学~");
System.out.println("--------------");
// 方式2:
// 打乱
Collections.shuffle(list);
String name2 = list.get(0);
System.out.println("随机点到了" + name2 + "同学~");
}
}
测试结果
随机点到了范闲同学~
--------------
随机点到了甄姬同学~
Process finished with exit code 0
2、点名器:带概率的随机点名
需求
- 班级里有N个学生,要求70%的概率随机到男生、30%的概率随机到女生。
分析
- 不要想得太复杂:
- 我们定义一个概率集合,存入7个1,存入3个0,7个1表示70%概率,3个0表示30%概率
- 那么我们就可以定义两个集合分别用于存储男生和女生的姓名
- 当随机到1的时候,就去男生的集合中随机一个名字出来
- 当随机到0的时候,就去女生的集合中随机一个名字出来
- 这样就可以解决了概率的问题了
测试类
package com.app.demo32_sets_test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class Test2 {
public static void main(String[] args) {
/*
小案例:自动点名器2
需求:
班级里有N个学生,要求70%的概率随机到男生、30%的概率随机到女生。
男生名字:"关羽", "范闲", "诸葛亮", "孙悟空", "马云", "宋合泛", "呼延烈"
女生名字:"波赛西", "小舞", "朱竹清", "甄姬", "蔡文姬"
*/
// 1.定义一个概率集合
ArrayList<Integer> probableList = new ArrayList<>();
// 2.存入7个1表示70%的概率,存入3个0表示30%的概率
Collections.addAll(probableList, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0);
// 3.将集合中所有的元素打乱
Collections.shuffle(probableList);
// 4.随机一个1或0
Random rd = new Random();
int index = rd.nextInt(probableList.size());
int number = probableList.get(index);
// System.out.println(number);
// 5.创建两个集合分别用于存储男生、女生的名字
ArrayList<String> boyList = new ArrayList<>();
ArrayList<String> girlList = new ArrayList<>();
// 6.分别往男生、女生的集合中添加名字
Collections.addAll(boyList, "关羽", "范闲", "诸葛亮", "孙悟空", "马云", "宋合泛", "呼延烈");
Collections.addAll(girlList, "波赛西", "小舞", "朱竹清", "甄姬", "蔡文姬");
// 7.随机点名
// 判断number是否为1
if (number == 1) {
// 是,则去男生的集合中随机一个名字出来
int boyIndex = rd.nextInt(boyList.size());
String boyName = boyList.get(boyIndex);
System.out.println("随机点到了" + boyName + "同学~");
} else {
// 否,则去女生的集合中随机一个名字出来
int girlIndex = rd.nextInt(girlList.size());
String girlName = girlList.get(girlIndex);
System.out.println("随机点到了" + girlName + "同学~");
}
}
}
测试结果
随机点到了呼延烈同学~
Process finished with exit code 0
3、点名器:不重复的随机点名
需求
- 班级里有N个学生,要求被点过的学生不会再被点到,但是如果班级中所有的学生都点完了,需要重新开启第二轮点名。
分析
- 先把随机点名写出来,然后再一步一步完善。
- 再实现被点过的学生不会再被点到。
- 再实现但是如果班级中所有的学生都点完了。
- 最后实现重新开启第二轮点名。
测试类
package com.app.demo32_sets_test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class Test3 {
public static void main(String[] args) {
/*
点名器:不重复的随机点名
需求
班级里有N个学生,要求被点过的学生不会再被点到,
但是如果班级中所有的学生都点完了,需要重新开启第二轮点名。
"关羽", "范闲", "诸葛亮", "孙悟空", "马云", "宋合泛", "呼延烈", "波赛西", "小舞", "朱竹清"
*/
// 1.定义集合,用于存储学生名字
ArrayList<String> nameList = new ArrayList<>();
// 2.添加名字到集合中
Collections.addAll(nameList, "关羽", "范闲", "诸葛亮", "孙悟空", "马云", "宋合泛",
"呼延烈", "波赛西", "小舞", "朱竹清");
// 3.创建一个临时的集合,用于将被点过的学生名字存储起来
ArrayList<String> tempList = new ArrayList<>();
// 4.随机点名
// 创建随机数对象
Random rd = new Random();
// 外循环:表示轮数
for (int i = 1; i <= 3; i++) {
System.out.println("=======第" + i + "轮随机点名开始=======");
// 为了避免每循环1次,集合长度-1的情况,先在内循环外将集合长度获取出来
int size = nameList.size();
// 内循环:每轮中随机循环抽取的过程
for (int j = 0; j < size; j++) {
// 生成一个随机索引
int index = rd.nextInt(nameList.size());
// 随机点一个名字出来,并将点到的学生删除掉,避免下次再点到
String name = nameList.remove(index);
// 将被点过的学生名字存储到临时集合中
tempList.add(name);
System.out.println(name);
}
// 5.循环结束,此时nameList集合已经空了,tempList已经将所有被点过的学生名字都存储起来了
// 每轮随机点名结束后,需要将tempList集合中的所有名字 重新给到 nameList集合
nameList.addAll(tempList);
// 然后将tempList集合清空,这样下一轮点名后,里面的数据才不会重复
tempList.clear();
}
}
}
测试结果
=======第1轮随机点名开始=======
小舞
范闲
宋合泛
呼延烈
孙悟空
波赛西
关羽
诸葛亮
马云
朱竹清
=======第2轮随机点名开始=======
朱竹清
范闲
诸葛亮
马云
关羽
波赛西
小舞
孙悟空
宋合泛
呼延烈
=======第3轮随机点名开始=======
孙悟空
呼延烈
范闲
马云
小舞
关羽
朱竹清
宋合泛
波赛西
诸葛亮
Process finished with exit code 0
二、小案例:省和市(集合嵌套)
需求
-
需要一个Map集合,键用省份名称(province),值用市(city),但是市会有多个。
-
添加完毕后,遍历结果格式如下:
江苏省 = 南京市,扬州市,苏州市,无锡市,常州市 湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市 河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市
测试类
package com.app.demo32_sets_test;
import java.util.*;
public class Test4 {
public static void main(String[] args) {
/*
案例:省和市(集合嵌套)
需求:
需要一个Map集合,键用省份名称(province),值用市(city),但是市会有多个。
添加完毕后,遍历结果格式如下:
江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市
*/
// 1.创建Map集合,键:省份名称,值:市(集合:多个城市)
HashMap<String, ArrayList<String>> hm = new HashMap<>();
// 2.创建单列集合,用于存储多个城市
ArrayList<String> city1 = new ArrayList<>();
// 添加城市
Collections.addAll(city1, "南京市", "扬州市", "苏州市", "无锡市", "常州市");
ArrayList<String> city2 = new ArrayList<>();
Collections.addAll(city2, "武汉市", "孝感市", "十堰市", "宜昌市", "鄂州市");
ArrayList<String> city3 = new ArrayList<>();
Collections.addAll(city3, "石家庄市", "唐山市", "邢台市", "保定市", "张家口市");
// 3.往Map集合中添加各个省份与各个省份的城市集合
hm.put("江苏省", city1);
hm.put("湖北省", city2);
hm.put("河北省", city3);
// 按照指定的格式拼接各个省份与各个省份的每个市
// 方式1
// 4.外循环:遍历Map集合,依次得到每个省份和市的集合(得到所有的键值对)
hm.forEach((province, citys) -> {
// 获取当前省份的所有市集合的长度
int size = citys.size();
// 先拼接当前省份(键对象)
System.out.print(province + " = ");
// 内循环:遍历当前省份的市集合,依次得到当前省份的每个市(得到所有的值对象)
for (int i = 0; i < size; i++) {
// 如果当前位置是集合中的末尾,则不拼接逗号,否则拼接逗号
System.out.print(i == size - 1 ? citys.get(i) : citys.get(i) + ",");
}
// 循环结束!说明当前省份的所有城市已经拼接完成!输出个换行
System.out.println();
});
System.out.println("---------------------------------------");
// 方式2
Set<Map.Entry<String, ArrayList<String>>> entries = hm.entrySet();
entries.forEach(entry -> {
// 获取所有的键对象
String province = entry.getKey();
// 获取所有的值对象的集合
ArrayList<String> citys = entry.getValue();
// 创建StringJoiner对象,用于按照指定的格式拼接各个省份与各个省份的所有城市
// 参数一:分隔符——>用逗号隔开;参数二:开始符——>不需要拼接任何东西;参数三:结束符:不需要拼接任何东西
StringJoiner sj = new StringJoiner(",", "", "");
// 遍历值对象集合,依次获取每个城市,并且拼接每个城市
citys.forEach(city -> sj.add(city));
// 输出最终拼接结果
System.out.println(province + " = " + sj);
});
}
}
测试结果
江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市
---------------------------------------
江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市
Process finished with exit code 0