# JAVA 实验三:掌握泛型类的原理和使用方法
# 实验任务书
“实验 3 说明” 文件夹中给出了一些源程序,完成以下要求:其中,StuList.java(假设其中的类实现了接口 MyList)中需要补充代码。
要求:
(注意,本次实验要做两个版本。
第一个版本是,排序时树映射的第一个泛型是封装类,测试程序时,会发现这种版本在学生成绩都不相同时是没有问题的,如果有成绩相同的情况,请观察程序的显示结果,看看有什么问题?
第二个版本是,对于第一个版本解决不了的问题,请自己思考,编写第二个版本,使得有成绩相同的情况,也都可以正确显示。)
(1)假设源程序 StuList.java 中的类实现了接口 MyList,创建源程序 MyList.java,其中的内容是接口 MyList 的声明。
(2)在 StuList.java 中根据要求补充代码。其中,学生信息不再存放在数组中,而是存放在双链表泛型类的对象中;排序时不再使用冒泡法或者选择法排序,而是使用树映射泛型类的对象进行排序输出。
(4)StuList.java,MyList.java,Undergraduate.java,Postgraduate.java 和 Student.java 在同一个包中。Main.java 在无名包中。
上述源程序可以完成如下任务:
创建学生链表,使用者根据提示信息,选择从键盘上输入本科生或者研究生的学生信息,将其加入学生链表,添加学生信息,删除学生信息,显示学生信息,按照学生成绩排序等。
# 解决
# 第一个版本
# 项目文件结构
├── src (源文件夹)
│ ├── students (包)
│ ├── Student.java (学生信息类(抽象类))
│ ├── StuList.java (实现接口 MyList)
│ ├── MyList.java (接口)
│ ├── Undergraduat.java (本科生类)
│ └── Postgraduate.java (研究生类)
│ ├── Main.java (位于无名包下)
# Main.java
| import student2.*; |
| import java.util.*; |
| |
| public class Main |
| { |
| public static void main(String[] args) |
| { |
| Scanner in=new Scanner(System.in); |
| StuList list=new StuList(); |
| int num; |
| System.out.println("要创建本科生信息表还是研究生信息表?\nA.本科生\tB.研究生"); |
| switch(in.next().charAt(0)) |
| { |
| case 'A': |
| case 'a': |
| System.out.println("请问要输入多少个本科生的信息?"); |
| num=in.nextInt(); |
| for(int i=0;i<num;i++) |
| { |
| System.out.println("请输入第"+(i+1)+"位学生的学号,姓名,数学、计算机成绩:"); |
| Student t=new Undergraduate(in.nextInt(),in.next(),in.nextDouble(),in.nextDouble()); |
| list.addStu(t); |
| } |
| list.addStu(new Undergraduate(1312,"shgd",99,98.5)); |
| list.addStu(new Undergraduate(1316,"ddsa",89,88.5)); |
| list.print(); |
| break; |
| case 'B': |
| case 'b': |
| System.out.println("请问要输入多少个研究生的信息?"); |
| num=in.nextInt(); |
| for(int i=0;i<num;i++) |
| { |
| System.out.println("请输入第"+(i+1)+"位学生的学号,姓名,数学、计算机成绩,导师和研究方向:"); |
| Student t=new Postgraduate(in.nextInt(),in.next(),in.nextDouble(),in.nextDouble(),in.next(),in.next()); |
| list.addStu(t); |
| } |
| list.addStu(new Postgraduate(1312,"shgd",99,98.5,"xyy","os")); |
| list.addStu(new Postgraduate(1316,"ddsa",89,88.5,"wcl","rgzn")); |
| list.print(); |
| break; |
| default: |
| System.out.println("输入错误!!!"); |
| break; |
| } |
| System.out.println("是否需要删除某个学生信息?输入y确定,输入其他继续:"); |
| String words=in.next(); |
| if(words.equals("Y")||words.equals("y")) |
| { |
| System.out.println("删除第几个同学?"); |
| list.removeStu(in.nextInt()); |
| System.out.println("最新的学生信息为:"); |
| list.print(); |
| list.sort(1); |
| list.sort(2); |
| in.close(); |
| } |
| else |
| { |
| System.out.println("最新的学生信息为:"); |
| list.print(); |
| list.sort(1); |
| list.sort(2); |
| in.close(); |
| } |
| } |
| } |
# Student.java
| package student2; |
| |
| public abstract class Student |
| { |
| int id; |
| String name; |
| double mathScore; |
| double computerScore; |
| |
| public Student(int id,String name,double mathScore,double computerScore) |
| { |
| this.id=id; |
| this.name=name; |
| this.mathScore=mathScore; |
| this.computerScore=computerScore; |
| } |
| |
| public int getId() |
| { |
| return id; |
| } |
| |
| public void setId(int id) |
| { |
| this.id = id; |
| } |
| |
| |
| public String getName() |
| { |
| return name; |
| } |
| |
| public void setName(String name) |
| { |
| this.name = name; |
| } |
| |
| |
| public double getMathScore() |
| { |
| return mathScore; |
| } |
| |
| public void setMathScore(double mathScore) |
| { |
| this.mathScore = mathScore; |
| } |
| |
| |
| public double getComputerScore() |
| { |
| return computerScore; |
| } |
| |
| public void setComputerScore(double computerScore) |
| { |
| this.computerScore = computerScore; |
| } |
| |
| public abstract void print(); |
| |
| } |
# StuList.java
| package student2; |
| import java.util.*; |
| |
| public class StuList implements MyList |
| { |
| LinkedList<Student> list; |
| |
| public StuList() |
| { |
| list=new LinkedList<Student>(); |
| } |
| |
| public int size() |
| { |
| return list.size(); |
| } |
| |
| public boolean addStu(Student x) |
| { |
| return list.add(x); |
| } |
| |
| public Student removeStu(int index) |
| { |
| return list.remove(index-1); |
| } |
| |
| public void clear() |
| { |
| list.clear(); |
| } |
| |
| public void sort(int x) |
| { |
| TreeMap<Double, Student>stuMap=new TreeMap<Double, Student>(); |
| Iterator<Student>iter=list.iterator(); |
| if(x==1) |
| { |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| stuMap.put(temp.getMathScore(),temp); |
| } |
| System.out.println("数学成绩从低到高排序为:"); |
| } |
| else if(x==2) |
| { |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| stuMap.put(temp.getComputerScore(),temp); |
| } |
| System.out.println("计算机成绩从低到高排序为:"); |
| } |
| Collection<Student>collection=stuMap.values(); |
| iter=collection.iterator(); |
| System.out.printf("共有%d名学生,信息如下:%n",stuMap.size()); |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| temp.print(); |
| } |
| } |
| public void print() |
| { |
| System.out.printf("共有%d名学生,信息如下:%n",list.size()); |
| Iterator<Student>iter=list.iterator(); |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| temp.print(); |
| } |
| } |
| } |
# MyList.java
| package student2; |
| |
| interface MyList { |
| public int size(); |
| public boolean addStu(Student x); |
| public Student removeStu(int index); |
| public void clear(); |
| public void sort(int x); |
| public void print(); |
| } |
# Undergraduat.java
| package student2; |
| |
| public class Undergraduate extends Student |
| { |
| public Undergraduate(int id,String name,double mathScore,double computerScore) |
| { |
| super(id,name,mathScore,computerScore); |
| } |
| |
| public void print() |
| { |
| System.out.printf("学号:%8d\t姓名:%8s\t数学成绩:%.1f\t计算机成绩:%.1f%n",getId(),getName(),getMathScore(),getComputerScore()); |
| } |
| } |
# Postgraduate.java
| package student2; |
| |
| public class Postgraduate extends Student |
| { |
| public String tutor; |
| public String researchArea; |
| |
| public Postgraduate(int id,String name,double mathScore,double computerScore,String tutor,String area) |
| { |
| super(id,name,mathScore,computerScore); |
| this.tutor=tutor; |
| this.researchArea=area; |
| } |
| public void print() |
| { |
| System.out.printf("学号:%8d\t姓名:%8s\t数学成绩:%.1f\t计算机成绩:%.1f\t导数姓名:%8s\t研究方向:%8s%n",getId(),getName(),getMathScore(),getComputerScore(),getTutor(),getResearchArea()); |
| } |
| |
| public String getTutor() |
| { |
| return tutor; |
| } |
| |
| public void setTutor(String tutor) |
| { |
| this.tutor = tutor; |
| } |
| |
| public String getResearchArea() |
| { |
| return researchArea; |
| } |
| |
| public void setResearchArea(String researchArea) |
| { |
| this.researchArea = researchArea; |
| } |
| |
| } |
# 第二个版本
# Stulist.java (改)
| package student2; |
| import java.util.*; |
| |
| class Key implements Comparable<Object> |
| { |
| double num=0; |
| Key(double num) |
| { |
| this.num=num; |
| } |
| public int compareTo(Object b) |
| { |
| Key t=(Key)b; |
| if(this.num == t.num) |
| return 1; |
| else |
| return (int)((this.num-t.num)*10); |
| } |
| } |
| |
| |
| public class StuList implements MyList |
| { |
| LinkedList<Student> list; |
| |
| public StuList() |
| { |
| list=new LinkedList<Student>(); |
| } |
| |
| public int size() |
| { |
| return list.size(); |
| } |
| |
| public boolean addStu(Student x) |
| { |
| return list.add(x); |
| } |
| |
| public Student removeStu(int index) |
| { |
| return list.remove(index-1); |
| } |
| |
| public void clear() |
| { |
| list.clear(); |
| } |
| |
| public void sort(int x) |
| { |
| |
| TreeMap<Key, Student>stuMap=new TreeMap<Key, Student>(); |
| Iterator<Student>iter=list.iterator(); |
| if(x==1) |
| { |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| |
| stuMap.put(new Key(temp.getMathScore()),temp); |
| } |
| System.out.println("数学成绩从低到高排序为:"); |
| } |
| else if(x==2) |
| { |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| |
| stuMap.put(new Key(temp.getComputerScore()),temp); |
| } |
| System.out.println("计算机成绩从低到高排序为:"); |
| } |
| Collection<Student>collection=stuMap.values(); |
| iter=collection.iterator(); |
| System.out.printf("共有%d名学生,信息如下:%n",stuMap.size()); |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| temp.print(); |
| } |
| } |
| public void print() |
| { |
| System.out.printf("共有%d名学生,信息如下:%n",list.size()); |
| Iterator<Student>iter=list.iterator(); |
| while(iter.hasNext()) |
| { |
| Student temp=iter.next(); |
| temp.print(); |
| } |
| } |
| } |
# 实验报告
# 实验目的
掌握泛型类的原理和使用方法
# 实验内容
“实验 3 说明” 文件夹中给出了一些源程序,完成以下要求:其中,StuList.java(假设其中的类实现了接口 MyList)中需要补充代码。
要求:
(注意,本次实验要做两个版本。
第一个版本是,排序时树映射的第一个泛型是封装类,测试程序时,会发现这种版本在学生成绩都不相同时是没有问题的,如果有成绩相同的情况,请观察程序的显示结果,看看有什么问题?
第二个版本是,对于第一个版本解决不了的问题,请自己思考,编写第二个版本,使得有成绩相同的情况,也都可以正确显示。)
(1)假设源程序 StuList.java 中的类实现了接口 MyList,创建源程序 MyList.java,其中的内容是接口 MyList 的声明。
(2)在 StuList.java 中根据要求补充代码。其中,学生信息不再存放在数组中,而是存放在双链表泛型类的对象中;排序时不再使用冒泡法或者选择法排序,而是使用树映射泛型类的对象进行排序输出。
(4)StuList.java,MyList.java,Undergraduate.java,Postgraduate.java 和 Student.java 在同一个包中。Main.java 在无名包中。
上述源程序可以完成如下任务:
创建学生链表,使用者根据提示信息,选择从键盘上输入本科生或者研究生的学生信息,将其加入学生链表,添加学生信息,删除学生信息,显示学生信息,按照学生成绩排序等。
# 实验结果
# 第一个版本
# 第二个版本
# 实验分析
1、由图可知,第一个版本中,如果出现学生成绩相同的情况下,只会保留一个人的成绩,其他成绩相同的人的成绩都会消失。第二个版本修复了这个问题。
2、用到了 LinkedList 和 TreeMap<K,V> 两个泛型类,其中利用 LinkedList list = new LinkedList (); 创建双链表泛型类对象 list 存储学生信息。
利用 Double 封装类,通过 TreeMap 是按键(学生的成绩)的升序排列。TreeMap<Double,Student>treemap=new TreeMap<Double,Student>()。但当学生成绩出现重复时,让 Key 类实现 Comparable 接口重写 CompareTo()方法。
TreeMap<Key,Student> treemap= new TreeMap<Key,Student>(); 实现重复成绩的学生不会被删除。
3. 对 Comparable 和 Comparator 接口的区别和用法不太理解。
Comparable 接口(排序接口)仅仅只包括一个函数,定义如下:
| package java.lang; |
| import java.util.*; |
| public interface Comparable { |
| public int compareTo(T o); |
| } |
| |
| |
| package java.util; |
| public interface Comparator { |
| int compare(T o1, T o2); |
| boolean equals(Object obj); |
| } |
int compare(T o1, T o2)
是 “比较 o1 和 o2 的大小”。返回 “负数”,意味着 “o1 比 o2 小”;返回 “零”,意味着 “o1 等于 o2”;返回 “正数”,意味着 “o1 大于 o2”, 若一个类要实现 Comparator 接口:它一定要实现 compareTo (T o1, T o2) 函数。
即:Comparable 是排序接口;若一个类实现了 Comparable 接口,就意味着 “该类支持排序”。. 而 Comparator 是比较器;我们若需要控制某个类的次序,可以建立一个 “该类的比较器” 来进行排序。Comparable 相当于 “内部比较器”,而 Comparator 相当于 “外部比较器。