package com.itheima;
import java.io.*;
import java.util.*;
/*
* 题目要求:
* 1、有五个学生,每个学生有3门课(语文、数学、英语)的成绩,
* 写一个程序接收从键盘输入学生的信息,输入格式为:name,30,30,30(姓名,三门课成绩)。
* 然后把输入的学生信息按总分从高到低的顺序写入到一个名称"stu.txt"文件中。
* 要求:stu.txt文件的格式要比较直观,打开这个文件,就可以很清楚的看到学生的信息。
*
*
* 结题思路:首先需要一个学生对象(Student),其次我们需要一个容器,来存放这些学生对象。
* 由于需要对学生对象按照成绩总分由高到低来排序,所以我们选择TreeSet。由于学生对象不具有比较性,
* 因此学生对象需要实现一个比较器接口,这里就使用了Comparable接口。学生对象放到容器中后需要保障
* 学生的唯一性,所以学生类必须重写Object类中equals方法来定义自己的区分方法。由于TreeSet放入
* 元素时,会先调用hashCode()方法。与容器中已存在的对象的hashCode作比较,如果相同,就调用一次equals()
* 方法来保障元素的唯一性,否则就不调用equals方法,而直接添加对象了,为了更好的保障元素的唯一性,我们需要覆盖
* hashCode()方法。输入学生信息时,由于输入流的来源是键盘,键盘输入的是字符,所以选用Reader类,为了更加高效,
* 使用BufferedReader类。这个类接受了一个InputStreamReader对象作为构造器参数,而InputStreamReader
* 需要一个InputStream对象作为其构造参数,因此就是用System.in对象,他是InputStream类型,成为"标准"输入流,
* 通常对应的就是键盘输入。把学生信息写入到磁盘文件stu.txt文档中。
*/
class Student implements Comparable<Student> {
private String name;
private int math, chinese, english;
private int sum;
Student(String name, int math, int chinese, int english) {
this.name = name;
this.math = math;
this.chinese = chinese;
this.english = english;
sum = math + chinese + english;
}
public String getName() {
return name;
}
public int getSum() {
return sum;
}
// 覆盖了默认的hashCode()方法以保证学生的唯一性
@Override
public int hashCode() {
return name.hashCode() + sum * 78;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Student)) // 判断传入的参数是否为Student类型,不是就会抛出类转型异常
throw new ClassCastException("类型不匹配");
Student s = (Student) obj;
return this.name.equals(s.name) && this.sum == s.sum; // 比较两个学生对象的姓名和总分数,相同则返回true,否则为false
}
// 实现接口所要求的方法,以便按我们所需要的方式排序学生对象
@Override
public int compareTo(Student o) {
int num = new Integer(this.sum).compareTo(new Integer(o.sum)); // 比较两个学生对象的总分数,以便按总分排序
if (num == 0) // 如果总分数相同,就比较姓名,次要条件就会以姓名排序
return this.name.compareTo(o.name);
return num;
}
// 自定义自己的打印学生对象方法
@Override
public String toString() {
return name + ",语文成绩:" + chinese + ",数学成绩:" + math + ",英语成绩:" + english;
}
}
// 收集学生信息的工具来
class StudentInfoTool {
public static Set<Student> getStudents() throws NumberFormatException,
IOException {
return getStudents(null);
}
// 从键盘获取学生信息,并存入到TreeSet集合中,该方法返回一个包含学生对象的Set集合
public static Set<Student> getStudents(Comparator<Student> cmp) // 传入一个比较器以便按需排序
throws NumberFormatException, IOException { // 为简化代码,就把异常直接抛出了,但实际开发中不能这么做
// 输入学生的信息,输入格式为:name,30,30,30(姓名,语文,数学,英语三门课成绩)。
System.out.println("输入学生的信息,输入格式为:name,30,30,30(姓名,语文,数学,英语三门课成绩)。");
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));
Set<Student> stus = null;
if (cmp == null)
stus = new TreeSet<Student>();
else
stus = new TreeSet<Student>(cmp);
String line = null;
while ((line = bufr.readLine()) != null) {
if ("".equals(line)) // 输入over就结束输入学生信息
break;
String[] info = line.split("\\,"); // 把输入的一行数据串按','切割以便获取姓名和各们课成绩数据
Student stu = new Student(info[0], Integer.parseInt(info[1]),
Integer.parseInt(info[2]), Integer.parseInt(info[3])); // 把获取的学生信息用来创建一个具体的学生对象
stus.add(stu); // 把学生对象添加到集合中
}
bufr.close(); // 关闭输入流,释放资源
return stus;
}
// 把存储有学生对象的集合写入到文件中
public static void write2File(Set<Student> stus, File f) throws IOException {
BufferedWriter bufw = new BufferedWriter(new FileWriter(f));
for (Student stu : stus) { // foreach语法
bufw.write(stu.toString() + "\t");
// bufw.write(stu.getSum() + "");
bufw.newLine(); // 写入一个行分隔符
bufw.flush(); // 刷新该流的缓冲,即把内存中的数据写入到文件中
}
bufw.close();
}
}
public class Test1 {
public static void main(String[] args) throws NumberFormatException,
IOException {
// sources为eclipse中java工程目录下的一个文件夹
File file = new File("stu.txt");
// 上面Student类实现了Comparable接口后,就会按总分数的自然顺序排序,即从低到高。但题目要求的是从高到低,而Collections的reverseOrder()方法就会强行逆转这个自然顺序,即从高到低了
Comparator<Student> cmp = Collections.reverseOrder();
Set<Student> stus = StudentInfoTool.getStudents(cmp); // 传入强行逆转后的比较器
StudentInfoTool.write2File(stus, file); // 把按总分排序的学生信息写入的文件中
System.out.println("学生的信息已经写到该项目目录下的stu.txt文档中。");
}
}
|
|