PTA题目集6-8的总结性Blog

发布时间 2023-06-23 21:42:16作者: 朱昱宽

一、前言

在这个PTA题目集中,涉及到了成绩计算中所需要的各种计算方式,容器-HashMap,容器-ArrayList,以及 jmu-Java-02基本语法和接口-自定义接口等方面的知识。总体来说,难度适中,但需要考生对这些概念有一定的了解。

二、设计与分析

首先是7-1 容器-HashMap-检索

输入多个学生的成绩信息,包括:学号、姓名、成绩。

学号是每个学生的唯一识别号,互不相同。

姓名可能会存在重复。

使用HashMap存储学生信息,并实现根据学号的检索功能

输入格式:

输入多个学生的成绩信息,每个学生的成绩信息格式:学号+英文空格+姓名+英文空格+成绩

以“end”为输入结束标志

end之后输入某个学号,执行程序输出该生的详细信息

输出格式:

输出查询到的学生信息格式:学号+英文空格+姓名+英文空格+成绩

如果没有查询到,则输出:"The student "+查询的学号+" does not exist"

 

分析

本题需要实现一个学生信息管理系统,涉及到学生信息的存储和查询。我们可以使用HashMap来存储学生信息,其中,学号作为key,学生信息作为value。在查询时,根据输入的学号,检索HashMap中是否存在该学生信息,并返回查询结果。如果没有查询到,输出相应的提示信息。

设计

首先,我们需要定义一个类来存储学生信息,包括学号、姓名和成绩。然后,我们可以使用HashMap来存储学生信息,其中,学号作为key,学生信息对象作为value。当用户输入学号时,我们可以通过HashMap的get方法获取该学生的信息对象,然后输出学生信息即可。如果没有查询到该学生,可以输出相应的提示信息。

总结

本题主要考察对HashMap的使用和对类的定义的掌握程度,需要注意输入格式的处理和异常情况的处理。从SourceMonitor的生成报表也能看出题目本身并不是很复杂。

 

 

接下来看一下容器-ArrayList-排序

输入多个学生的成绩信息,包括:学号、姓名、数学成绩、物理成绩。学号是每个学生的唯一识别号,互不相同。姓名可能会存在重复。因此,可以考虑将学生信息封装成一个类,类中包含学号、姓

名、数学成绩、物理成绩等属性,并重写equals()和hashCode()方法,以保证学号的唯一性。

使用ArrayList存储学生信息,可以遍历ArrayList计算每个学生的数学成绩和物理成绩之和,然后按照题目要求排序输出。

输出格式:学号+英文空格+姓名+英文空格+数学/物理成绩之和。

下列代码可以参考

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;
// 定义学生类
class Student {
private String id; // 学号
private String name; // 姓名
private int mathScore; // 数学成绩
private int physicsScore; // 物理成绩
// 构造方法
public Student(String id, String name, int mathScore, int physicsScore) {
this.id = id;
this.name = name;
this.mathScore = mathScore;
this.physicsScore = physicsScore;
}
// 封装方法
public String getId() {
return id;
}
public String getName() {
return name;
}
public int getMathScore() {
return mathScore;
}
public int getPhysicsScore() {
return physicsScore;
}
// 重写equals()方法和hashCode()方法
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || !(obj instanceof Student)) {
return false;
}
Student other = (Student) obj;
return this.id.equals(other.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
// 计算数学成绩和物理成绩之和
public int getScoreSum() {
return mathScore + physicsScore;
}
// 重写toString()方法
@Override
public String toString() {
return id + " " + name + " " + getScoreSum();
}
}
public class StudentScoreSort {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Student> list = new ArrayList<>();
String input = scanner.nextLine();
while (!input.equals("end")) {
String[] arr = input.split(" ");
String id = arr[0];
String name = arr[1];
int mathScore = Integer.parseInt(arr[2]);
int physicsScore = Integer.parseInt(arr[3]);
Student student = new Student(id, name, mathScore, physicsScore);
list.add(student);
input = scanner.nextLine();
}
scanner.close();
// 按照数学成绩和物理成绩之和排序
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int sum1 = s1.getScoreSum();
int sum2 = s2.getScoreSum();
if (sum1 != sum2) {
return sum2 - sum1; // 从高到低排序
} else {
return list.indexOf(s1) - list.indexOf(s2); // 按照输入先后顺序排序
}
}
});
// 输出学生信息
for (Student student : list) {
System.out.println(student);
}
}
}

 

 

然后再是7-5 jmu-Java-03面向对象基础-05-覆盖
 

PersonOverride类设计

  1. 属性设计
    • String类型的name属性
    • int类型的age属性
    • boolean类型的gender属性 所有属性都必须是私有属性(private)。
  2. 构造方法设计
    • 有参构造方法,参数为name, age, gender
    • 无参构造方法,使用this(name, age,gender)调用有参构造方法。参数值分别为"default",1,true
  3. equals方法设计 比较name、age、gender,这三者内容都相同,才返回true。
  4. toString方法设计 返回格式为:name-age-gender

Main方法设计

  1. 输入n1,使用无参构造方法创建n1个对象,放入ArrayList persons1。
  2. 输入n2,然后指定name age gender。每创建一个对象都使用equals方法比较该对象是否已经在ArrayList中存在,如果不存在,才将该对象放入ArrayList persons2。
  3. 输出persons1中的所有对象
  4. 输出persons2中的所有对象
  5. 输出persons2中实际包含的对象的数量5
  6. 输出PersonOverride的所有构造方法。

import java.util.ArrayList;
import java.util.Arrays;
class PersonOverride {
private String name;
private int age;
private boolean gender;
public PersonOverride(String name, int age, boolean gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public PersonOverride() {
this("default", 1, true);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PersonOverride) {
PersonOverride person = (PersonOverride) obj;
return person.name.equals(this.name) && person.age == this.age && person.gender == this.gender;
}
return false;
}
@Override
public String toString() {
return name + "-" + age + "-" + gender;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<PersonOverride> persons1 = new ArrayList<>();
ArrayList<PersonOverride> persons2 = new ArrayList<>();
int n1 = 3;
int n2 = 3;
// 创建n1个PersonOverride对象并添加到persons1中
for (int i = 0; i < n1; i++) {
persons1.add(new PersonOverride());
}
// 创建n2个PersonOverride对象并添加到persons2中
for (int i = 0; i < n2; i++) {
String name = "name" + i;
int age = i;
boolean gender = i % 2 == 0;
PersonOverride person = new PersonOverride(name, age, gender);
if (!persons2.contains(person)) {
persons2.add(person);
}
}
// 输出persons1中的所有对象
System.out.println("persons1:");
for (PersonOverride person : persons1) {
System.out.println(person.toString());
}
// 输出persons2中的所有对象
System.out.println("persons2:");
for (PersonOverride person : persons2) {
System.out.println(person.toString());
}
// 输出persons2中实际包含的对象的数量
System.out.println("persons2包含的对象数量:" + persons2.size());
// 输出PersonOverride的所有构造方法
System.out.println(Arrays.toString(PersonOverride.class.getConstructors()));
}
}

优点:

重写了equals方法,可以正确判断两个PersonOverride对象是否相等。

重写了toString方法,可以将PersonOverride对象以字符串形式输出。

用ArrayList存储PersonOverride对象,方便动态添加和删除元素。

通过contains方法和equals方法判断PersonOverride对象是否已经存在于ArrayList中,避免了重复添加。

缺点:

PersonOverride类中的属性和构造方法较为简单,可能无法满足实际需求。

没有使用泛型,可能会导致类型不安全的问题。

没有对输入的n1和n2进行校验,可能会导致程序异常。

只输出了PersonOverride类的构造方法,没有输出其他方法和属性,可能会导致信息不全。

 

 三、踩坑心得

 

import java.util.Arrays;
import java.util.Scanner;
interface IntegerStack {
Integer push(Integer item);
Integer pop();
Integer peek();
boolean empty();
int size();
}
class ArrayIntegerStack implements IntegerStack {
private int top = -1;
private final int capacity;
private final Integer[] array;
public ArrayIntegerStack(int capacity) {
this.capacity = capacity;
this.array = new Integer[capacity];
}
@Override
public Integer push(Integer item) {
if (item == null || top == capacity - 1) {
return null;
}
array[++top] = item;
return item;
}
@Override
public Integer pop() {
if (top == -1) {
return null;
}
return array[top--];
}
@Override
public Integer peek() {
if (top == -1) {
return null;
}
return array[top];
}
@Override
public boolean empty() {
return top == -1;
}
@Override
public int size() {
return top + 1;
}
@Override
public String toString() {
return Arrays.toString(array);
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if (!scanner.hasNextInt()) {
scanner.close();
return;
}
int n = scanner.nextInt();
ArrayIntegerStack stack = new ArrayIntegerStack(n);
for (int i = 0; i < n; i++) {
if (!scanner.hasNextInt()) {
scanner.close();
return;
}
int value = scanner.nextInt();
Integer result = stack.push(value);
System.out.println(result);
}
Integer top = stack.peek();
if (top == null) {
System.out.println("null");
} else {
System.out.println(top);
}
System.out.format("%b,%d\n", stack.empty(), stack.size());
System.out.println(stack);
if (!scanner.hasNextInt()) {
scanner.close();
return;
}
int x = scanner.nextInt();
for (int i = 0; i < x; i++) {
Integer result = stack.pop();
if (result == null) {
System.out.println("null");
} else {
System.out.println(result);
}
}
top = stack.peek();
if (top == null) {
System.out.println("null");
} else {
System.out.println(top);
}
System.out.format("%b,%d\n", stack.empty(), stack.size());
System.out.println(stack);
scanner.close();
}
}这是改进前代码

import java.util.Arrays;
import java.util.Scanner;
interface IntegerStack {
Integer push(Integer item);
Integer pop();
Integer peek();
boolean empty();
int size();
}
class ArrayIntegerStack implements IntegerStack {
private int top = -1;
private int capacity;
private Integer[] array;
public ArrayIntegerStack(int capacity) {
this.capacity = capacity;
this.array = new Integer[capacity];
}
@Override
public Integer push(Integer item) {
if (item == null) {
return null;
}
if (top == capacity - 1) {
capacity *= 2;
array = Arrays.copyOf(array, capacity);
}
array[++top] = item;
return item;
}
@Override
public Integer pop() {
if (top == -1) {
return null;
}
Integer item = array[top--];
if (top < capacity / 2) {
capacity /= 2;
array = Arrays.copyOf(array, capacity);
}
return item;
}
@Override
public Integer peek() {
if (top == -1) {
return null;
}
return array[top];
}
@Override
public boolean empty() {
return top == -1;
}
@Override
public int size() {
return top + 1;
}
@Override
public String toString() {
return Arrays.toString(Arrays.copyOfRange(array, 0, top + 1));
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if (!scanner.hasNextInt()) {
scanner.close();
return;
}
int n = scanner.nextInt();
ArrayIntegerStack stack = new ArrayIntegerStack(n);
for (int i = 0; i < n; i++) {
if (!scanner.hasNextInt()) {
scanner.close();
return;
}
int value = scanner.nextInt();
Integer result = stack.push(value);
System.out.println(result);
}
Integer top = stack.peek();
if (top == null) {
System.out.println("null");
} else {
System.out.println(top);
}
System.out.format("%b,%d\n", stack.empty(), stack.size());
System.out.println(stack);
if (!scanner.hasNextInt()) {
scanner.close();
return;
}
int x = scanner.nextInt();
for (int i = 0; i < x; i++) {
Integer result = stack.pop();
if (result == null) {
System.out.println("null");
} else {
System.out.println(result);
}
}
top = stack.peek();
if (top == null) {
System.out.println("null");
} else {
System.out.println(top);
}
System.out.format("%b,%d\n", stack.empty(), stack.size());
System.out.println(stack);
scanner.close();
}
}

改进后有以下优点

  1. 在push方法中加入自动扩容的功能,可以避免栈空间不足的情况,避免使用者频繁扩容,提高了栈的效率;
  2. 在pop方法中加入缩容的功能,可以避免栈空间浪费,提高了栈的效率;
  3. 使用Arrays.copyOf方法来复制数组,可以让代码更加简洁易懂;
  4. 使用Arrays.toString方法来打印数组,可以让代码更加简洁易懂。

四、改进建议

  1. 可以使用封装性更好的List<PersonOverride>代替ArrayList<PersonOverride>
  2. 可以使用for-each循环代替for循环;
  3. 可以使用System.out.printf代替System.out.println输出格式更清晰的信息;
  4. 可以使用@Override注解确保重写的方法正确性;
  5. 可以使用Objects.equals代替==比较两个对象是否相等

 五、总结

  不知不觉也已经到学期末了,在学习过程中,我发现深入理解Java编程语言的面向对象思想对于程序设计至关重要。熟练掌握Java编程语言不仅能够使我们写出规范、高效的代码,还能够提高我们的编程思维,为今后的软件开发打下坚实的基础。 总之,这个学期的Java学习让我收获颇丰,不仅熟悉了编程语言本身,也懂得了如何运用编程思维解决具体问题。我相信,这些知识和经验将对我的日后学习和工作产生深远的影响。