实验目的
熟悉集合类的应用,熟悉String类的应用以及正则表达式的使用。
实验内容
1
张三、李四等人是A社团成员,李四、王五等人是B社团成员,编写一个Java应用程序(要求使用集合类),输出参加A社团的人、参加B社团的人、以及同时参加两个社团的人。在报告中附上程序截图、完整的运行结果截图和详细的文字说明。
package problem1;
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<String> clubA = new HashSet<>();
clubA.add("张三");
clubA.add("李四");
clubA.add("王五");
clubA.add("蔡徐坤");
clubA.add("小黑子");
clubA.add("王源");
Set<String> clubB = new HashSet<>();
clubB.add("李四");
clubB.add("王五");
clubB.add("赵六");
clubB.add("丁真");
clubB.add("王源");
System.out.println("参加A社团的人员:");
for (String member : clubA) {
System.out.println(member);
}
System.out.println("\n参加B社团的人员:");
for (String member : clubB) {
System.out.println(member);
}
Set<String> bothMembers=new HashSet<>(clubA);
bothMembers.retainAll(clubB);
System.out.println("\n同时参加两个社团的人员:");
for (String member : bothMembers) {
System.out.println(member);
}
}
}
运行结果截图:
文字说明:
该程序创建了两个HashSet对象,分别表示社团A和社团B的成员。然后,使用add方法向每个HashSet添加成员的姓名。接下来,遍历并打印出参加社团A和社团B的成员。
然后,创建了一个新的HashSet对象bothMembers,并将其初始化为社团A的成员。然后,使用retainAll方法传入社团B的成员,以找出同时参加两个社团的人员。最后,遍历bothMembers集合,打印出同时参加两个社团的人员
2
在2023年杭州亚运会中,获得奖牌数最多的十支队伍的金、银、铜牌数量如下表所示:
将上面表格信息作为输入(顺序不变),编写一个Java应用程序,使用TreeMap<K,V>,按照银牌数量从小到大排序输出10支队伍的信息,要求通过两种方式实现:通过实现Comparator接口和通过实现Comparable接口。在报告中附上程序截图、完整的运行结果截图和详细的文字说明。
第一种方法,通过实现Comparator接口:
package problem2;
import java.util.*;
class team{
private String name;
private int gold;
private int silver;
private int bronze;
private int total;
public team(String nname, int g, int s, int b,int t) {
this.name = nname;
this.gold = g;
this.silver = s;
this.bronze = b;
this.total=t;
}
public int getSilver(){
return this.silver;
}
public void print() {
System.out.println("Team:" + this.name + " Gold:" + this.gold + " Silver" + this.silver + " Bronze:" + this.bronze + " Total:" + this.total);
}
}
class SilverComparator implements Comparator<team> {
@Override
public int compare(team team1, team team2) {
return team1.getSilver() - team2.getSilver();
}
}
public class Method1 {
public static void main(String[] args) {
TreeMap<team, Integer> kun = new TreeMap<>(new SilverComparator());
team[] teams = {
new team("CHN", 201, 111, 71,383),
new team("JPN",52,67,69,188),
new team("KOR", 42, 59, 89,190),
new team("IND",28,38,41,107),
new team("UZB",22,18,31,71),
new team("TPE",19,20,28,67),
new team("IRI",13,21,20,54),
new team("THA",12,14,32,58),
new team("BRN",12,3,5,20),
new team("PRK",11,18,10,39),
};
for (team a : teams) {
kun.put(a, a.getSilver());
}
Collection<team> collection = kun.keySet();
Iterator<team> iter = collection.iterator();
while (iter.hasNext()) {
team te = iter.next();
te.print();
}
}
}
运行结果截图:
文字说明:
该程序写了一个team 类,用来表示一支队伍的信息,包含了团队的名称、金牌数、银牌数、铜牌数和总奖牌数。它具有构造函数、获取银牌数的方法 getSilver() 和打印团队信息的方法 print()。SilverComparator 类实现了 Comparator 接口,用于按照团队的银牌数进行排序。它重写了 compare() 方法,根据团队的银牌数进行比较。在 main() 方法中,创建了一个 TreeMap<team, Integer> 类型的对象 kun,并将 SilverComparator 实例传递给它作为比较器。然后,创建了一些team 对象,并将它们作为键,银牌数作为值,存放到 kun 中。接下来,通过调用 kun.keySet() 方法获取 kun 中的键的集合。然后,使用迭代器遍历这个键的集合,并逐个调用 print() 方法打印每个团队的信息。
第二种方法:,通过实现Comparable接口:
package problem2;
import java.util.*;
class tteam implements Comparable<tteam>{
private String name;
private int gold;
private int silver;
private int bronze;
private int total;
public tteam(String nname, int g, int s, int b,int t) {
this.name = nname;
this.gold = g;
this.silver = s;
this.bronze = b;
this.total=t;
}
public int getSilver(){
return this.silver;
}
public void print() {
System.out.println("Team:" + this.name + " Gold:" + this.gold + " Silver" + this.silver + " Bronze:" + this.bronze + " Total:" + this.total);
}
@Override
public int compareTo(tteam other){
return this.getSilver()-other.getSilver();
}
}
public class Method2 {
public static void main(String[] args) {
TreeMap<tteam, Integer> kun = new TreeMap<>();
tteam[] teams = {
new tteam("CHN", 201, 111, 71, 383),
new tteam("JPN", 52, 67, 69, 188),
new tteam("KOR", 42, 59, 89, 190),
new tteam("IND", 28, 38, 41, 107),
new tteam("UZB", 22, 18, 31, 71),
new tteam("TPE", 19, 20, 28, 67),
new tteam("IRI", 13, 21, 20, 54),
new tteam("THA", 12, 14, 32, 58),
new tteam("BRN", 12, 3, 5, 20),
new tteam("PRK", 11, 18, 10, 39),
};
for (tteam a : teams) {
kun.put(a, a.getSilver());
}
Collection<tteam> collection = kun.keySet();
Iterator<tteam> iter = collection.iterator();
while (iter.hasNext()) {
tteam te = iter.next();
te.print();
}
}
}
运行结果截图:
文字说明:
该代码编写了一个 tteam 类,tteam 类用来表示一支队伍的信息,包含了团队的名称、金牌数、银牌数、铜牌数和总奖牌数。它具有构造函数、获取银牌数的方法 getSilver() 和打印团队信息的方法 print(),同时,它实现了 Comparable 接口,重写了 compareTo() 方法,用于按照团队的银牌数进行比较。在 main() 方法中,创建了一个 TreeMap<tteam, Integer> 类型的对象 kun,然后,创建了一些 tteam 对象,并将它们作为键,银牌数作为值,存放到 kun 中。接下来,通过调用 kun.keySet() 方法获取 kun 中的键的集合。然后,使用迭代器遍历这个键的集合,并逐个调用 print() 方法打印每个团队的信息。
3
编写Java应用程序。新建一个ArrayList对象、一个LinkedList对象,一个HashSet对象、一个LinkedHashSet对象、以及一个TreeSet对象。每个对象都包含1到50000的所有整数,顺序随机。现进行如下测试:i) 产生10000个随机整数,每个对象调用contains方法判断这些整数是否在该对象中;ii)计算每个对象执行这10000次操作所需要的时间,并进行对比分析。
package problem3;
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();
Set<Integer> hashSet = new HashSet<>();
Set<Integer> linkedHashSet = new LinkedHashSet<>();
Set<Integer> treeSet = new TreeSet<>();
List<Integer> numbers = new ArrayList<>();
for (int i = 1; i <= 50000; i++) {
numbers.add(i);
}
Collections.shuffle(numbers);
arrayList.addAll(numbers);
linkedList.addAll(numbers);
hashSet.addAll(numbers);
linkedHashSet.addAll(numbers);
treeSet.addAll(numbers);
Random random = new Random();
int[] randomNumbers = new int[10000];
for (int i = 0; i < 10000; i++) {
randomNumbers[i] = random.nextInt(50000) + 1;
}
long startTime, endTime, duration;
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
arrayList.contains(randomNumbers[i]);
}
endTime = System.currentTimeMillis();
duration = endTime - startTime;
System.out.println("ArrayList执行10000次contains方法所需时间:" + duration + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
linkedList.contains(randomNumbers[i]);
}
endTime = System.currentTimeMillis();
duration = endTime - startTime;
System.out.println("LinkedList执行10000次contains方法所需时间:" + duration + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
hashSet.contains(randomNumbers[i]);
}
endTime = System.currentTimeMillis();
duration = endTime - startTime;
System.out.println("HashSet执行10000次contains方法所需时间:" + duration + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
linkedHashSet.contains(randomNumbers[i]);
}
endTime = System.currentTimeMillis();
duration = endTime - startTime;
System.out.println("LinkedHashSet执行10000次contains方法所需时间:" + duration + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
treeSet.contains(randomNumbers[i]);
}
endTime = System.currentTimeMillis();
duration = endTime - startTime;
System.out.println("TreeSet执行10000次contains方法所需时间:" + duration + "ms");
}
}
运行结果截图:
文字说明:
在这个程序中,首先创建了五个集合:arrayList、linkedList、hashSet、linkedHashSet 和 treeSet。接着创建了一个包含 1 到 50000 的整数的列表 numbers。然后使用 Collections.shuffle() 方法将列表中的元素随机排序。然后,将随机排序后的 numbers 列表的元素添加到各个集合中。然后使用 Random 类生成了一个大小为 10000 的随机整数数组 randomNumbers,其中每个随机数介于 1 到 50000 之间。
接下来,使用 System.currentTimeMillis() 记录了每个集合执行 contains() 方法的时间。在一个循环中,分别对 arrayList、linkedList、hashSet、linkedHashSet 和 treeSet 进行 10000 次 contains() 方法的调用,查找 randomNumbers 数组中的元素。最后,计算每个集合执行 contains() 方法所需的时间,并将结果打印出来。
分析:根据输出的结果,可以看出不同集合类型在执行 contains() 方法时的性能差异。
ArrayList 执行 10000 次 contains() 方法所需时间为 204 毫秒,LinkedList 执行 10000 次 contains() 方法所需时间为 388 毫秒,HashSet 执行 10000 次 contains() 方法所需时间为 4 毫秒,LinkedHashSet 执行 10000 次 contains() 方法所需时间为 1 毫秒,TreeSet 执行 10000 次 contains() 方法所需时间为 5 毫秒。因此,在需要频繁进行元素查找操作的情况下,HashSet 和 LinkedHashSet 是更好的选择,它们提供了较快的查找性能。而如果需要保持元素的排序状态,TreeSet 也是一个不错的选择。而 ArrayList 和 LinkedList 在查找操作方面的性能较差,适用于其他操作,如添加、删除和遍历等。
4
编写Java应用程序,统计分析网页https://en.szu.edu.cn/About/About2.htm 中关于深圳大学的介绍的英文文章(包括题目About)中每个英文单词出现的次数(不区分大小写,不要写爬虫,可以把整篇文章的内容当作一个字符串读入),并输出出现次数最多的50个英文单词(按出现次数排序,每行输出10个英文单词,共5行)。在报告中附上程序截图、完整的运行结果截图和简要文字说明。
package problem4;
import java.util.*;
public class Main {
public static void main(String[] args) {
String s = "About Shenzhen University (SZU) is committed to excellence in teaching, research and social service. Sticking to the motto of “self-reliance, self-discipline, self-improvement”, the University is dedicated to serving the Shenzhen Special Economic Zone (SEZ), demonstrating China’s reform and opening up and pioneering change in higher education. SZU, which is based in Shenzhen, China’s first Special Economic Zone and a key city in the Guangdong-Hong Kong-Macau Greater Bay Area, is distinctively known as an Experimental University in higher education with its reforms in the sector acknowledged in Mainland China. Established in 1983, SZU received support from top Chinese universities including Peking University, Tsinghua University and Renmin University of China in the founding of new schools. In the past decades, the University has undergone rapid growth and has become a comprehensive university with complete disciplines, top-ranked academic and research institutes and awe-inspiring faculty. SZU faculty members are engaged with teaching and research for the betterment of society. They are devoted to seeking solutions to pressing global challenges and promoting innovation. SZU offers a wide array of undergraduate and graduate programs and provides students with an interdisciplinary and inclusive multicultural learning environment. Students in SZU enjoy the plenty resources and facilities of both the SEZ and the University, pursue academic excellence and discover new interests and opportunities in a fast-changing era. SZU is an integral part of the SEZ, a thriving technology and innovation hub. With two campuses in Yuehai and Lihu, the University vigorously conducts leading researches in various fields and collaborates with high-tech enterprises in the community for technology transfer. SZU strives to provide a high-quality and effective education and develop in each SZU member the ability and passion to innovate and contribute to social progress and development, and encourages talented young people to start entrepreneurship in SZU. Our alumni including Tencent have founded dozens of innovative companies with significant influence. SZU is accelerating its pace toward internationalization, providing a variety of global learning opportunities. The University has established partnerships with numbers of overseas universities to offer exceptional exchange programs, joint degree programs, research collaborations, and a variety of other forms of collaborations with international partners. Students from all over the world are welcomed in SZU. In the city noted for its urban vitality and natural beauty, students can explore the most attractive parts of China, pursue their passion and develop their interests, perspectives and abilities.";
String new_string = s.toLowerCase().replaceAll("[^a-z ]", "");
String[] words = new_string.split("\\s+");
Map<String,Integer> countMap = new HashMap<>();
for (String word : words) {
countMap.put(word, countMap.getOrDefault(word, 0) + 1);
}
List<Map.Entry<String,Integer>> result = new ArrayList<>(countMap.entrySet());
result.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));
System.out.println("出现次数最多的50个单词:");
int cnt=0;
for (Map.Entry<String, Integer> entry : result) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.print(key + ":" + value + "次 ");
++cnt;
if (cnt % 10==0) {
System.out.println();
}
if (cnt == 50) {
break;
}
}
}
}
运行结果截图:
文字说明:
该程序将网页https://en.szu.edu.cn/About/About2.htm 中关于深圳大学的介绍的英文文章(包括题目About)的内容作为一个字符串,然后利用正则表达式将所有非字母的字符转化为空字符,并将大写字母转化为小写,然后将字符串按照一个或多个连续的空格进行分割,然后将分割后的单词存储到words数组中,然后遍历该数组,将每个单词存进countMap中,然后将 countMap 中的键值对(单词及其出现次数)转换为一个 ArrayList 列表 result,使用 Map.Entry.comparingByValue() 方法结合 Comparator.reverseOrder(),按照单词的出现次数进行降序排序,最后按照题目要求的格式打印输出结果。
5
package problem5;
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String,Double> menu=new HashMap<>();
menu.put("北京烤鸭",199.1);
menu.put("西芹炒肉",11.8);
menu.put("酸菜鱼",59.1);
menu.put("铁板牛柳",33.1);
Double sum_price=0.0;
Iterator<Double> iterator = menu.values().iterator();
while (iterator.hasNext()) {
double price = iterator.next();
sum_price += price;
}
System.out.println("菜单的总价格为:"+sum_price);
}
}
运行结果截图:
文字说明:
该程序创建了一个 HashMap 类型的 menu 映射,其中键是字符串类型,值是双精度浮点数类型,表示菜品名称和对应的价格。然后,初始化 sum_price 变量为 0.0,用于累计菜单的总价格。接下来使用 menu.values().iterator() 获取值的集合,并通过调用 iterator() 方法获取一个 Iterator 迭代器。这个迭代器用于遍历 menu 映射中的值。在循环中,使用 iterator.hasNext() 检查是否还有下一个元素。如果有,则通过 iterator.next() 获取下一个元素(即价格),并将其加到 sum_price 变量中。最后,输出菜单的总价格。
6
编写Java应用程序,每次从键盘读入一个包含有大写英文字母、小写英文字母和数字混杂的字符串(例如Aa123bEFGaaa49023),要求按顺序输出大写英文字母(例如AEFG)、小写英文字母(abaaa)和数字(12349023)。要求循环连续测试10次,在报告中附上程序截图、完整的运行结果截图和简要文字说明。
package problem6;
import java.util.*;
public class Main {
public static void main(String[] args) {
int t = 10;
for(int i=0;i<10;i++){
Scanner scanner = new Scanner(System.in);
System.out.print("输入字符串:");
String input = scanner.nextLine();
StringBuilder daxie = new StringBuilder();
StringBuilder xiaoxie = new StringBuilder();
StringBuilder shuzi = new StringBuilder();
for (char c : input.toCharArray()) {
if (Character.isUpperCase(c)) {
daxie.append(c);
} else if (Character.isLowerCase(c)) {
xiaoxie.append(c);
} else if (Character.isDigit(c)) {
shuzi.append(c);
}
}
System.out.println("大写英文字母:" + daxie.toString());
System.out.println("小写英文字母:" + xiaoxie.toString());
System.out.println("数字:" + shuzi.toString());
System.out.println("---------------------------------");
}
}
}
运行结果截图:
文字说明:
该程序每次从键盘读入一个包含有大写英文字母、小写英文字母和数字混杂的字符串,然后声明了daxie,xiaoxie,shuzi三个StringBuilder对象,然后对输入的字符串的每个字符进行判断,将字符所属的类别,存入对应的对象,最后按顺序输出大写英文字母、小写英文字母和数字,整个循环共测试了10次。
7
编写Java应用程序,根据用户输入的5个时间(每行一个时间),计算相邻两个时间之间的间隔,共4个结果。注:用户输入的时间格式为“××××年××月××日××时××分××秒”,输出的时间格式为“××日××时××分××秒”。在报告中附上程序截图、完整的运行结果截图和简要文字说明。
package problem7;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
LocalDateTime[] times = new LocalDateTime[5];
for (int i = 0; i < 5; i++) {
String input = scanner.nextLine();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒");
LocalDateTime time = LocalDateTime.parse(input, formatter);
times[i] = time;
}
for (int i = 0; i < 4; i++) {
LocalDateTime startTime = times[i];
LocalDateTime endTime = times[i + 1];
Duration duration = Duration.between(startTime, endTime);
long days = duration.toDays();
long hours = duration.toHoursPart();
long minutes = duration.toMinutesPart();
long seconds = duration.toSecondsPart();
if(days<0){
duration = Duration.between(endTime, startTime);
days = duration.toDays();
hours = duration.toHoursPart();
minutes = duration.toMinutesPart();
seconds = duration.toSecondsPart();
}
System.out.println("第"+(i+1)+"个时间和第"+(i+2)+"个时间间隔为:" + days + "日" + hours + "时" + minutes + "分" + seconds + "秒");
}
}
}
/*
2022年05月07日21时49分42秒
2025年08月19日18时23分55秒
2024年02月14日06时28分14秒
2023年01月25日14时12分07秒
2026年06月06日15时55分21秒
*/
运行结果截图:
文字说明:
该程序首先创建一个Scanner对象来读取用户的输入,然后创建一个长度为5的LocalDateTime数组来存储输入的时间。接下来,使用一个循环来读取用户输入的五个时间,并使用DateTimeFormatter将输入的字符串解析为LocalDateTime对象,并将其存储在数组中。然后,计算相邻两个时间之间的时间间隔,通过使用Duration.between方法来计算两个时间的时间间隔。然后,程序将相差时间转换为天数、小时、分钟和秒,并将结果打印出来。如果计算得到的天数小于0,说明时间顺序有误,交换开始时间和结束时间,并重新计算相差时间。最后,程序打印出每个时间间隔的结果。