题目
实验目的
掌握常用异常的处理方法;掌握常用集合的基本用法;理解泛型及其应用。
实验要求
独立完成实验,并撰写实验报告。
实验内容
-
使用异常机制处理程序错误
为下面的代码加入适当的异常处理, 使得该程序可以处理输入的字符串不为数字字符串的情况(要求重新输入,最后得到3个从键盘输入的浮点数)。public static void main(String[] args) { double[] x = new double[3];double sum = 0.0; Scanner inputScan = new Scanner(System.in); for(int i = 0; i < x.length;i++){ System.out.println("Please input the "+(i+1)+" number:"); String input = inputScan.nextLine(); x[i] = Double.parseDouble(input); sum += x[i]; } System.out.println(Arrays.toString(x)); System.out.println("Sum:" + sum); }
-
List与Iterator接口
(1)编写NameDao接口,包含如下方法://将数组中的字符串放入列表,该方法需要使用ListIterator接口实现添加 public List getNameFromArray(String[] names); //在列表中搜索到与name相同的项目,就返回该name所在的序号,找不到返回-1。 public int searchName(List nameList, String name); //根据指定id,从列表中移除指定的项目,如果id指定错误(负数或者超出列表最大值)抛出IllegalArgumentException异常,移除成功返回true public boolean removeFromList(List nameList, int id);
(2)编写NameDaoImpl实现NameDao接口。
(3)编写一个测试类,测试上述代码的功能。 -
Map与HashMap
- (1)编写Student类,只有String name与int age两个属性和他们的setter/getter方法,覆盖其hashCode与equals方法。
- (2)在Util类中编写方法:List getRandomStudents(int n)随机生成n个学生的列表。
说明:调用“基础代码”中的Util.getRandomName (int min, int max)获取随机名字,调用public static int getRandomAge(int min, int max)生成随机年龄。 - (3)在Util类中编写方法:public static Map<string, student=“”> makeStudentMap(List);,将List中每个Student的name作为key, Student对象本身作为value放入Map中,并返回。
- (4)在Util类中编写方法:public static String searchName(List nameList, String name);,根据指定的name返回相应的字符串,如果没有找到返回null。
- (5)在Util类中编写方法:public static Student searchStudent(Map<string,student> stuMap, String name);,根据指定的name返回对应的学生,如果没有找到返回null。
- (6)在Util类中编写方法:public static List generateNameList(int n);,生成n个字符串的NameList并返回。
- (7)在Util类中编写方法:Map<string, student=“”> generateStudentMap(int n);,生成包含n个键的的StudentMap并返回。
说明:调用getRandomStudents方法;调用makeStudentMap方法;返回StudentMap。 - (8)对比测试。在初始化阶段调用generateNameList方法生成nameList列表,里边包含1000万个字符串。在初始化阶段调用getRandomStudents生成1000万个Student对象,然后调用makeStudentMap方法生成stuMap映射表。
对nameList调用searchName方法搜索指定字符串并统计执行时间。
对stuMap调用searchStudent方法搜索指定字符串对应的学生对象并统计执行时间。
思考:步骤(8)中,哪个方法搜索速度快?为什么? - (9)遍历输出StudentMap前10个的key,前10个value,前10个entry。
备注:可以设置虚拟机选项,让JVM能够拥有大内存。
★Eclipse中的设置方法:打开Window->Preferences菜单,左边列选择Java->Installed JREs,在需要设置的JRE上,点击Edit,设置Default VM arguments的值为“-Xms1024m -Xmx4096m”,其中-Xms设置最小内存,-Xmx设置最大内存。
★IDEA中的设置方法:选择Help->Edit Custom VM Options,修改-Xms和-Xmx为相应的内存值,如-Xms1024m、-Xmx4096m。
- Collections
- (1)改写Student类,增加int grade属性。
- (2)随机生成100个Student对象放入students数组。
- (3)将students数组转换成studentList(List类型)。
- (4)使用Collections.sort对student的成绩进行排序。
- (5)使用Collections的min和max方法找到成绩最高的和成绩最低学生。
- (6)使用Collections的binarySearch查找成绩等于60的学生。
- (7)编写方法从studentList找出grade小于60的学生,放入otherList。
- (8)使用List的removeAll方法,从studentList中移除otherList。
- (9)使用Collections的shuffle方法,打乱studentList中学生排列的顺序。
- (10)将studentList转换为数组。
参考资料
Student.java
package collectionTest;
public class Student{
private String name;
private int 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 int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
Util.java
package collectionTest;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
public class Util {
/**
*
* @param
* @return 返回分布在[0,upLimit]的随机整数
*/
public static int getRandomNumber(int upLimit) {
return new Random().nextInt(upLimit+1);
}
/**
*
* @param min
* @param max
* @return 返回分布在[min,max]的随机整数
*/
public static int getRandomNumber(int min,int max){
if(min > max){
throw new IllegalArgumentException("min ="+min+">"+ "max="+max);
}
return min + new Random().nextInt(max+1-min);
}
/**
*
* @param min
* @param max
* @return 返回长度在min到max之间随机名字
*/
public static String getRandomName(int min, int max){
StringBuilder sb = new StringBuilder();
int n = getRandomNumber(min, max);
while (n>0) {
sb.append((char)getRandomNumber('a','z'));
n--;
}
return sb.toString();
}
}
实验报告
一、目的
掌握常用异常的处理方法;
掌握常用集合的基本用法;
理解泛型及其应用。
二、实验内容与设计思想
1.设计思路
(1) 使用异常机制处理程序错误
(2) List与Iterator接口
(3) Map与HashMap
(4) Collections
主要数据结构
问题三 |
| 学生类,包含名字与年龄属性 |
问题四 |
| 改良的学生类,包含名字、年龄与成绩属性 |
主要代码结构
三、实验使用环境
软件:java version “18.0.2”,EclipseIDE 2022-06
平台:win10
四、实验步骤和调试过程
exp1:使用异常机制处理程序错误
需求
加入适当的异常处理,
使得该程序可以处理输入的字符串不为数字字符串的情况(要求重新输入,最后得到3个从键盘输入的浮点数)。
实验步骤
Error类
package exp1;
import java.util.Arrays;
import java.util.Scanner;
public class Error
{
public static void main(String[] args) {
double[] x = new double[3];
double sum = 0.0;
Scanner inputScan = new Scanner(System.in);
for(int i = 0; i < x.length;i++){
System.out.println("Please input the "+(i+1)+" number:");
String input = inputScan.nextLine();
try
{
x[i] = Double.parseDouble(input);
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("输入的不是数字,请重新输入");
i--;
continue;
}
sum += x[i];
}
System.out.println(Arrays.toString(x));
System.out.println("Sum:" + sum);
}
}
测试数据设计
输入三个数字,其中夹杂错误输入字母或符号
测试结果分析
exp2:List与Iterator接口
需求
(1)编写NameDao接口,包含如下方法:
**public List getNameFromArray(String\[\] names);** //在列表中搜索到与name相同的项目,就返回该name所在的序号,找不到返回-1。 public int searchName(List nameList, String name);** //根据指定id,从列表中移除指定的项目,如果id指定错误(负数或者超出列表最大值)抛出IllegalArgumentException异常,移除成功返回true public boolean removeFromList(List nameList, int id);
(2)编写NameDaoImpl实现NameDao接口。
(3)编写一个测试类,测试上述代码的功能。
实验步骤
NameDao接口
package exp2;
import java.util.List;
public interface NameDao
{
public List getNameFromArray(String[] names);
public int searchName(List nameList, String name);
public boolean removeFromList(List nameList, int id) throws Exception;
}
NameDaoImpl类
package exp2;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
public class NameDaoImpl implements NameDao
{
public List getNameFromArray(String[] names)
{
List nameList = new ArrayList();
ListIterator li = nameList.listIterator();
for(String name:names)
li.add(name);
return nameList;
}
public int searchName(List nameList, String name)
{
return nameList.indexOf(name);
}
public boolean removeFromList(List nameList, int id) throws Exception
{
if(id>=0&&id<nameList.size())
{
nameList.remove(id);
return true;
}
else
{
try
{
throw new IllegalArgumentException();
}
catch (IllegalArgumentException e2)
{
System.out.println("Catch an IllegalArgumentException..."+e2.getMessage()+",不存在这个id");
return false;
}
}
}
}
Test类
package exp2;
import java.util.List;
public class Test
{
public static void main(String[] args) throws Exception
{
NameDao nameDao = new NameDaoImpl();
String[] names = new String[]{"张三", "李四", "王五"};
List list = nameDao.getNameFromArray(names);
int index = nameDao.searchName(list,"张三");
if(index!=-1)
System.out.println("找到了,位置在"+index);
else
System.out.println("没有这个名字");
index = nameDao.searchName(list,"孙六");
if(index!=-1)
System.out.println("找到了,位置在"+index);
else
System.out.println("没有这个名字");
boolean isRemove = nameDao.removeFromList(list,0);
if(isRemove)
System.out.println("删除成功");
isRemove = nameDao.removeFromList(list,5);
if(isRemove)
System.out.println("删除成功");
}
}
测试数据设计
使用一个数组:测试getNameFromArray功能
测试searchName功能:使用存在和不存在的序号进行测试
测试removeFromList功能:使用存在和不存在的id进行测试
测试结果分析
exp3:Map与HashMap
需求
(1)编写Student类,只有String name与int
age两个属性和他们的setter/getter方法,覆盖其hashCode与equals方法。(2)在Util类中编写方法:List getRandomStudents(int
n)随机生成n个学生的列表。说明:调用"基础代码"中的Util.getRandomName (int min, int
max)获取随机名字,调用public static int getRandomAge(int min, int
max)生成随机年龄。(3)在Util类中编写方法:public static Map<string,
student=“”> makeStudentMap(List);,将List中每个Student的name作为key,
Student对象本身作为value放入Map中,并返回。(4)在Util类中编写方法:public static String searchName(List nameList,
String name);,根据指定的name返回相应的字符串,如果没有找到返回null。(5)在Util类中编写方法:public static Student
searchStudent(Map<string,student> stuMap, String
name);,根据指定的name返回对应的学生,如果没有找到返回null。(6)在Util类中编写方法:public static List generateNameList(int
n);,生成n个字符串的NameList并返回。(7)在Util类中编写方法:Map<string,
student=“”> generateStudentMap(int
n);,生成包含n个键的的StudentMap并返回。说明:调用getRandomStudents方法;调用makeStudentMap方法;返回StudentMap。
(8)对比测试。在初始化阶段调用generateNameList方法生成nameList列表,里边包含1000万个字符串。在初始化阶段调用getRandomStudents生成1000万个Student对象,然后调用makeStudentMap方法生成stuMap映射表。
对nameList调用searchName方法搜索指定字符串并统计执行时间。
对stuMap调用searchStudent方法搜索指定字符串对应的学生对象并统计执行时间。
思考:步骤(8)中,哪个方法搜索速度快?为什么?
(9)遍历输出StudentMap前10个的key,前10个value,前10个entry。
实验步骤
Student类
package exp3;
import java.util.Objects;
public class Student{
private String name;
private int 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 int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.getAge())
return false;
if (name == null) {
if (other.getName() != null)
return false;
} else if (!name.equals(other.getName()))
return false;
return true;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
Util类
package exp3;
import com.sun.jdi.PathSearchingVirtualMachine;
import java.util.*;
public class Util
{
//随机生成n个学生的列表
public static List<Student> getRandomStudents(int n)
{
List<Student>students = new ArrayList<>();
for(int i=0;i<n;i++)
students.add(new Student(getRandomName(3,7),getRandomNumber(18,27)));
return students;
}
//将List中每个Student的name作为key, Student对象本身作为value放入Map中,并返回。
public static Map<String, Student> makeStudentMap(List<Student> students)
{
Map<String,Student>studentMap = new HashMap<>();
for(Student student:students)
studentMap.put(student.getName(),student);
return studentMap;
}
//根据指定的name返回相应的字符串,如果没有找到返回null
public static String searchName(List<String> nameList, String name)
{
int index = nameList.indexOf(name);
if(index==-1)
return null;
return nameList.get(index);
}
//生成n个字符串的NameList并返回
public static List<String> generateNameList(int n)
{
List<String>nameList = new ArrayList<>();
for(int i=0;i<n;i++)
{
nameList.add(getRandomName(3,7));
}
return nameList;
}
public static Map<String, Student> generateStudentMap(int n)
{
List<Student> students = getRandomStudents(n);
return makeStudentMap(students);
}
public static Student searchStudent(Map<String, Student>studentMap,String name)
{
return studentMap.get(name);
}
//返回分布在[0,upLimit]的随机整数
public static int getRandomNumber(int upLimit) {
return new Random().nextInt(upLimit+1);
}
//返回分布在[min,max]的随机整数
public static int getRandomNumber(int min,int max){
if(min > max){
throw new IllegalArgumentException("min ="+min+">"+ "max="+max);
}
return min + new Random().nextInt(max+1-min);
}
//返回长度在min到max之间随机名字
public static String getRandomName(int min, int max){
StringBuilder sb = new StringBuilder();
int n = getRandomNumber(min, max);
while (n>0) {
sb.append((char)getRandomNumber('a','z'));
n--;
}
return sb.toString();
}
}
Test类
package exp3;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import static exp3.Util.*;
public class Test
{
public static void main(String[] args)
{
//对比测试
List<String> names = generateNameList(10000);
List<Student> students = getRandomStudents(10000);
Map<String,Student> studentMap = makeStudentMap(students);
long startTime=System.nanoTime(); //获取开始时间
String name = searchName(names,names.get(5000));
long endTime=System.nanoTime(); //获取结束时间
System.out.println("searchName程序运行时间: "+(endTime-startTime)+"ns");
startTime=System.nanoTime(); //获取开始时间
Student student = searchStudent(studentMap,name);
endTime=System.nanoTime(); //获取结束时间
System.out.println("searchStudent程序运行时间: "+(endTime-startTime)+"ns");
System.out.println();
//遍历输出
int i = 0;
for(Entry entry:studentMap.entrySet())
{
if(++i>10)
break;
System.out.println(entry.getKey());
System.out.println(entry.getValue());
System.out.println(entry);
System.out.println();
}
}
}
测试数据设计
设计对比测试,测试searchName和searchStudent的执行时间。
输出StudentMap前10个的key,前10个value,前10个entry。
测试结果分析
searchName程序运行时间: 713500ns
searchStudent程序运行时间: 8700ns
107104114102103
exp3.Student@9543d901
107104114102103=exp3.Student@9543d901
112110115
exp3.Student@e38ce822
112110115=exp3.Student@e38ce822
110110122117113
exp3.Student@3cab0166
110110122117113=exp3.Student@3cab0166
112110118
exp3.Student@e38ce880
112110118=exp3.Student@e38ce880
121105108122121
exp3.Student@a156a381
121105108122121=exp3.Student@a156a381
112109121
exp3.Student@e256e64e
112109121=exp3.Student@e256e64e
99102105119102
exp3.Student@b58639
99102105119102=exp3.Student@b58639
118112121117
exp3.Student@976bd894
118112121117=exp3.Student@976bd894
122120118104
exp3.Student@e4f12a7a
122120118104=exp3.Student@e4f12a7a
109119106108119
exp3.Student@84fb0b9f
109119106108119=exp3.Student@84fb0b9f
exp4:Collections
需求
(1)改写Student类,增加int grade属性。
(2)随机生成100个Student对象放入students数组。
(3)将students数组转换成studentList(List类型)。
(4)使用Collections.sort对student的成绩进行排序。
(5)使用Collections的min和max方法找到成绩最高的和成绩最低学生。
(6)使用Collections的binarySearch查找成绩等于60的学生。
(7)编写方法从studentList找出grade小于60的学生,放入otherList。
(8)使用List的removeAll方法,从studentList中移除otherList。
(9)使用Collections的shuffle方法,打乱studentList中学生排列的顺序。
(10)将studentList转换为数组。
实验步骤
Student2类
package exp4;
import java.util.Objects;
public class Student2
{
String name;
int age;
int grade;
public Student2(String name, int age, int grade)
{
this.name = name;
this.age = age;
this.grade = grade;
}
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;
}
public int getGrade()
{
return grade;
}
public void setGrade(int grade)
{
this.grade = grade;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student2 student2 = (Student2) o;
return age == student2.age && grade == student2.grade && Objects.equals(name, student2.name);
}
@Override
public int hashCode()
{
return Objects.hash(name, age, grade);
}
}
Test类
package exp4;
import java.util.*;
public class Test
{
//返回分布在[0,upLimit]的随机整数
public static int getRandomNumber(int upLimit) {
return new Random().nextInt(upLimit+1);
}
//返回分布在[min,max]的随机整数
public static int getRandomNumber(int min,int max){
if(min > max){
throw new IllegalArgumentException("min ="+min+">"+ "max="+max);
}
return min + new Random().nextInt(max+1-min);
}
//返回长度在min到max之间随机名字
public static String getRandomName(int min, int max){
StringBuilder sb = new StringBuilder();
int n = getRandomNumber(min, max);
while (n>0) {
sb.append((char)getRandomNumber('a','z'));
n--;
}
return sb.toString();
}
//随机生成n个学生的列表
public static Student2[] getRandomStudent2s(int n)
{
Student2[] student2s = new Student2[n];
for(int i=0;i<n;i++)
student2s[i] = new Student2(getRandomName(3,7),getRandomNumber(10,50),getRandomNumber(0,100));
return student2s;
}
//将students数组转换成studentList(List类型)
public static List<Student2> makeStudentList(Student2[] students)
{
List<Student2> student2List = new ArrayList<>();
Collections.addAll(student2List,students);
return student2List;
}
public static void main(String[] args)
{
Student2[] student = getRandomStudent2s(100);
List<Student2> studentList = makeStudentList(student);
Collections.sort(studentList, (Student2 o1, Student2 o2)->o1.getGrade()-o2.getGrade());
System.out.println("成绩最高的学生为:"+Collections.min(studentList,(Student2 o1, Student2 o2)->o1.getGrade()-o2.getGrade()).getName());
System.out.println("成绩最低的学生为:"+Collections.max(studentList,(Student2 o1, Student2 o2)->o1.getGrade()-o2.getGrade()).getName());
int index = Collections.binarySearch(studentList,new Student2("",0,60),(Student2 o1,Student2 o2)->o1.getGrade()-o2.getGrade());
if (index>=0)
System.out.println("成绩等于60的学生为"+studentList.get(index).getName());
else
System.out.println("没有成绩等于60的学生");
List<Student2> otherList = getDisqualifiedStudent(studentList);
studentList.removeAll(otherList);
Collections.shuffle(studentList);
Student2[] studentsArr = makeStudentArray(studentList);
}
public static List<Student2> getDisqualifiedStudent(List<Student2> studentList)
{
List<Student2> otherList = new ArrayList<>();
for(Student2 student2:studentList)
if(student2.getGrade()<60)
otherList.add(student2);
return otherList;
}
public static Student2[] makeStudentArray(List<Student2> student2List)
{
return (Student2[]) student2List.toArray(new Student2[student2List.size()]);
}
}
测试数据设计
测试生成100个学生到数组
测试数组转List
测试List转数组
测试寻找成绩最高,最低和等于60的学生
测试removeAll和shuffle功能
测试结果分析
五、实验小结
实验中遇到的问题及解决过程
无
实验中产生的错误及原因分析
无
实验体会和收获。
掌握了常用异常的处理方法;
掌握了常用集合的基本用法;
理解了泛型及其应用。