【Java】集合工具类Collections练习

练习一:随机点名器的两种实现方法

需求:班级里有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 随机出来的是那个点,它不能表示链。

image-20240429092950062

那我们该怎么实现呢?

我们可以往集合中添加 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 ,表示当前的元素是否删除成功
  • 根据索引删,它会返回被删除的元素
image-20240429094501145
 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();
}

练习四:带权重的随机点名项目

image-20240429101110070

这一题会涉及到后面的知识点,因此这里先写不了。

其中这里的 带权重随机算法 还是很重要的:在以后,我们会学习到微服务架构,那为什么会有微服务呢?

其实就是因为现在上网的人太多了,一台服务器扛不住了,就需要将一个大项目拆分成n个小项目,部署在n个服务器中。

但是这就会有一个小问题:用户在上网的时候,我也不知道访问哪个服务器。

所以在中间就会有一个服务网关,它会根据一些算法计算出,现在哪台服务器的压力还比较小。

其中有一个算法叫做:带权重的随机,随机到哪台服务器,用户就会去访问所对应的服务器,这样的好处就是可以能让我们的项目去被更多的人访问。

一开始我们可以给每台服务器都设置权重为1,那就表示每台服务器所随机到的概率是一样的。

image-20240505171537016

但是假设,现在有一台服务器访问的人数太多了,此时我们就可以将它的权重降低,如果降到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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值