练习一:随机点名器的两种实现方法
需求:班级里有N个学生,实现随机点名器
//1.定义集合
ArrayList<String> list = new ArrayList<>();
//2.添加数据
Collections.addAll(list,"范闲","范建","范统","杜子腾","杜琦燕","宋合泛","侯笼藤","朱益群","朱穆朗玛峰","袁明媛");
//3.随机点名
// 第一种方式:(以前的写法)
Random r = new Random();
int index = r.nextInt(list.size());
String name = list.get(index);
System.out.println(name);
//第二种方式:打乱
Collections.shuffle(list);
//既然已经打乱了,直接获取到0索引位置的数据就行了
String name = list.get(0);
System.out.println(name);
练习二:随机点名器的两种实现方法
需求:班级里有N个学生,要求在随机的时候,70%的概率随机到男生,30%的概率随机到女生
这题中,Random
是不能直接使用的,我们以前是拿着 Random
随机出一堆数据,这种随机数据叫做 随机点
。
例如范围是 1 ~20
,如果随机出来的是 13
,那么这个 13
表示的是数字 13
还是 1 ~ 13
这个范围呢?
很明显,它仅仅只能表示自己 13
这个数据。
因此 Random
随机出来的是那个点,它不能表示链。
那我们该怎么实现呢?
我们可以往集合中添加 7个1、3个0
,此时7个1
在整体的数字中占 70%
,0占30%
。
然后将集合打乱顺序,打乱完后,从这个集合中抽 0
或者 1
。
- 如果抽到了
1
,那么就从男生里面随机 - 如果抽到
0
,那么就从女生里面随机
//1.创建集合
ArrayList<Integer> list = new ArrayList<>();
//2.添加数据
Collections.addAll(list,1,1,1,1,1,1,1);
Collections.addAll(list,0,0,0);
//3.打乱集合中的数据
Collections.shuffle(list);
//4.从list集合中随机抽取0或者1
Random r = new Random();
int index = r.nextInt(list.size());
int number = list.get(index);
System.out.println(number);
//5.创建两个集合分别存储男生和女生的名字
ArrayList<String> boyList = new ArrayList<>();
ArrayList<String> girlList = new ArrayList<>();
Collections.addAll(boyList,"范闲","范建","范统","杜子腾","宋合泛","侯笼藤","朱益群","朱穆朗玛峰");
Collections.addAll(girlList,"杜琦燕","袁明媛","李猜","田蜜蜜");
//6.判断此时是从boyList里面抽取还是从girlList里面抽取
if(number == 1){
//boyList
int boyIndex = r.nextInt(boyList.size());
String name = boyList.get(boyIndex);
System.out.println(name);
}else{
//girlList
int girlIndex = r.nextInt(girlList.size());
String name = girlList.get(girlIndex);
System.out.println(name);
}
练习三:自动点名器
需求:班级里有N个学生,被点到的学生不会再被点到。但是如果班级中所有的学生都点完了, 需要重新开启第二轮点名。
//1.定义集合
ArrayList<String> list1 = new ArrayList<>();
//2.添加数据
Collections.addAll(list1, "范闲", "范建", "范统", "杜子腾", "杜琦燕", "宋合泛", "侯笼藤", "朱益群", "朱穆朗玛峰", "袁明媛");
在随机的时候,可以随机一个删一个。
Random r = new Random();
int index = r.nextInt(list.size());
String name = list.get(index);
list.remove(name);
上面随机名字和删除名字其实是可以合成一行的,这是因为 remove()
有两个方法
- 根据元素删,返回
boolean
,表示当前的元素是否删除成功 - 根据索引删,它会返回被删除的元素
String name = list.remove(index);
但如果直接这么写,那么每运行一次程序都会创建一个新的集合,并没有达到题目想要抽取到所有人的目的,因此需要使用循环来改善。
Random r = new Random();
for (int i = 0; i < list.size(); i++) {
int index = r.nextInt(list.size());
String name = list.get(index);
list.remove(name);
}
首先我们需要知道:集合的长度是可以发生变化的,在一开始的时候,集合的长度是 10
。
满足 i < 10,即 0 < 10
,第一次进入循环,删除元素成功后,集合的长度就变为了 9
。
满足 i < 9,即 0 < 9
,第一次进入循环,删除元素成功后,集合的长度就变为了 9
。
…以此类推
由此可见,问题出在:list.size()
是变化的。
解决办法:在上面重新定义一个变量。
int count = list.size();
Random r = new Random();
for (int i = 0; i < count; i++) {
int index = r.nextInt(list.size());
String name = list.get(index);
list.remove(name);
}
但是由于题目还有个要求:如果班级中所有的学生都点完了, 需要重新开启第二轮点名。
那么此时删掉的名字就不能真正的删,还需要再拿个集合存起来。
//创建一个临时的集合,用来存已经被点到学生的名字
ArrayList<String> list2 = new ArrayList<>();
//外循环:表示轮数
for (int i = 1; i <= 10; i++) {
System.out.println("=========第" + i + "轮点名开始了======================");
//3.获取集合的长度
int count = list1.size();
//4.随机点名
Random r = new Random();
//内循环:每一轮中随机循环抽取的过程
for (int j = 0; j < count; j++) {
int index = r.nextInt(list1.size());
String name = list1.remove(index);
list2.add(name);
System.out.println(name);
}
//此时表示一轮点名结束
//将list2的数据全部加到list1中
list1.addAll(list2);
list2.clear();
}
练习四:带权重的随机点名项目
这一题会涉及到后面的知识点,因此这里先写不了。
其中这里的 带权重随机算法
还是很重要的:在以后,我们会学习到微服务架构,那为什么会有微服务呢?
其实就是因为现在上网的人太多了,一台服务器扛不住了,就需要将一个大项目拆分成n个小项目,部署在n个服务器中。
但是这就会有一个小问题:用户在上网的时候,我也不知道访问哪个服务器。
所以在中间就会有一个服务网关,它会根据一些算法计算出,现在哪台服务器的压力还比较小。
其中有一个算法叫做:带权重的随机,随机到哪台服务器,用户就会去访问所对应的服务器,这样的好处就是可以能让我们的项目去被更多的人访问。
一开始我们可以给每台服务器都设置权重为1,那就表示每台服务器所随机到的概率是一样的。
但是假设,现在有一台服务器访问的人数太多了,此时我们就可以将它的权重降低,如果降到0的话,就不会再随机到这台服务器了。
不想打字了,以后有时间再补
练习五:集合嵌套
需求:定义一个Map集合,键用表示省份名称province,值表示市city,但是市会有多个。
添加完毕后,遍历结果格式如下:江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
之前我们说过,Map集合
如果没有特殊要求,那么默认使用 HashMap
,因为它的效率最高。
//1.创建Map集合
HashMap<String, ArrayList<String>> hm = new HashMap<>();
//2.创建单列集合存储市
ArrayList<String> city1 = new ArrayList<>();
city1.add("南京市");
city1.add("扬州市");
city1.add("苏州市");
city1.add("无锡市");
city1.add("常州市");
ArrayList<String> city2 = new ArrayList<>();
city2.add("武汉市");
city2.add("孝感市");
city2.add("十堰市");
city2.add("宜昌市");
city2.add("鄂州市");
ArrayList<String> city3 = new ArrayList<>();
city3.add("石家庄市");
city3.add("唐山市");
city3.add("邢台市");
city3.add("保定市");
city3.add("张家口市");
//3.把省份和多个市添加到map集合
hm.put("江苏省",city1);
hm.put("湖北省",city2);
hm.put("河北省",city3);
Set<Map.Entry<String, ArrayList<String>>> entries = hm.entrySet();
for (Map.Entry<String, ArrayList<String>> entry : entries) {
//entry依次表示每一个键值对对象
String key = entry.getKey();
ArrayList<String> value = entry.getValue();
StringJoiner sj = new StringJoiner(", ","","");
for (String city : value) {
sj.add(city);
}
System.out.println(key + " = " + sj);
}