# 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

# Stulist.java (改)

package student2;
import java.util.*;
class Key implements Comparable<Object>   // 新添加的类 Key
{ 
	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<Double, Student>stuMap=new TreeMap<Double, Student>(); // 原来
		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 (temp.getMathScore (),temp);   // 原来
				stuMap.put(new Key(temp.getMathScore()),temp);  // 改后
			}
			System.out.println("数学成绩从低到高排序为:");
		}
		else if(x==2)			// 按计算机成绩排序
		{
			while(iter.hasNext())
			{
				Student temp=iter.next();
				//stuMap.put (temp.getComputerScore (),temp);  // 原来
				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 在无名包中。
上述源程序可以完成如下任务:
创建学生链表,使用者根据提示信息,选择从键盘上输入本科生或者研究生的学生信息,将其加入学生链表,添加学生信息,删除学生信息,显示学生信息,按照学生成绩排序等。

# 实验结果

# 第一个版本

imgbed.cn图床

# 第二个版本

imgbed.cn图床

# 实验分析

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);
}
// 通过 x.compareTo (y) 来 “比较 x 和 y 的大小”。若返回 “负数”,意味着 “x 比 y 小”;返回 “零”,意味着 “x 等于 y”;返回 “正数”,意味着 “x 大于 y”.
//Comparator 接口(比较器)仅仅只包括两个函数,定义如下:
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 相当于 “外部比较器。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Lavender 微信支付

微信支付

Lavender 支付宝

支付宝