作者:酥软大仙 2019-12-20
本题不难就是烦,爷用了3个半小时完成这题!
更加让我没想到的是写这份文档用了4小时.....
先进入一波VScode的教程
如果您用的是VScode,这可能会很有用!如果不是,请跳过
如何用VScode快速覆写重构
我们在code内,需要覆写的地方右键
即可发现有一个叫源代码操作的东东
然后在里面这些东西
第一个是统一Import的组织格式
第二个是通用的覆写方法
点一下以后在最上面选择要覆写的函数就可以开始覆写了
第三个是覆写equals()
和hashCode()
这里两个结合在一起是因为通常来说这两个方法要一起覆写,不然可能会出错
第四个是覆写toString()
第五个是构建构造函数
创建类的时候,当我们把变量定义好以后就可以用这个直接写出构建函数
教程结束!
来让我们先来看看需要import的包
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
可以看得出来还是非常多的啊!
题目的第一句要求是这样的
定义Person抽象类,Student类、Company类,Employee类。
万事开头难,我们先来看第一个!
Person抽象类
这里Person类要求是抽象类,实际操作的时候我们可以创建普通类。并没有什么区别
题目要求:
Person类的属性:
String name, int age, boolean gender
啊这个简单,以下是Person类的实际构建代码:
abstract class Person implements Comparable<Person>{
private String name;
private int age;
private boolean gender;
Q:卧槽开头的abstract
是啥玩意啊,我记得构建一个类只要写class Person
就好了啊
A:abstract
是抽象类的标识符,写了abstract
就代表这个类是抽象类了!
Q:卧槽那后面implement Comparable<person>
是什么玩意啊,从来没见过啊
A:题目后面会要求我们对输入的信息进行排序,这一串东西是排序所需要的接口。java文档里告诉我们这个接口就是这么写的
题目要求:
Person类的方法:
public Person(String name, int age, boolean gender); public String toString(); //返回"name-age-gender"格式的字符串 public boolean equals(Object obj);//比较name、age、gender,都相同返回true,否则返回false
很显然第一个是构建函数,第二第三个是要覆写的
这个也简单,照着要求来,以下是Person类的实际覆写内容
public Person(String name,int age,boolean gender){
this.name=name;
this.age=age;
this.gender=gender;
}
@Override
public String toString() {
return name+"-"+age+"-" + gender;
}
@Override
public boolean equals(Object obj) {
Person eq = (Person) obj;
if( eq.name.equals(this.name) && eq.age==this.age && eq.gender==this.gender)
return true;
else
return false;
}
Person类中还需要定义一下get和set函数以便于访问和设置变量
以下是Person类中需要定义的方法,感谢无名英雄VScode帮我写完这段代码:
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 boolean isGender() {
return gender;
}
public void setGender(boolean gender) {
this.gender = gender;
}
那如果你有认真看上文的话,就会知道题目后面会要求我们对输入的信息进行排序
什么你不知道?您忘性真大
往上翻!看看那一段 Q&A 以及 Q&A 上面的那段代码!那边有写
为了实现排序呢,我在定义类的时候就加了一段代码implement Comparable<person>
当时在 Q&A 里说了啊,这是加了一个用以排序的接口
这个接口为了实现排序,是对我们提出了要求的!
他要求:类的内部有一个叫compareTo()
的方法,可以实现对象的比较。
好!那我们就来写一个方法!
以下是Person类内的compareTo()
方法:
@Override
public int compareTo(Person o) {
int nameCompare = this.getName().compareTo(o.getName()) ;//比较姓名
if(nameCompare==0){//如果姓名相同
int ageCompare=this.getAge()-o.getAge();//比较年龄
return ageCompare;//返回比较结果
}
return nameCompare;//返回比较结果
}
}
Q:你怎么知道要这么写啊!
A:这个具体的返回值是什么,怎么比较,那也不是我发明的,是java文档有规定的,我只是一个无情的抄袭带师...
恭喜,至此,Person类已经写完了!
Student类
题目要求:
Student类继承自
Person
,属性:String stuNo, String clazz
实现这一点并不难的,以下为实际代码:
class Student extends Person{
private String stuNo,clazz;
题目要求:
Student类的方法:
//建议使用super复用Person类的相关有参构造函数 public Student(String name, int age, boolean gender, String stuNo, String clazz); public String toString(); //返回 “Student:person的toString-stuNo-clazz”格式的字符串 public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true,则继续比较stuNo与clazz。
照着写啦~
public Student(String name, int age, boolean gender, String stuNo, String clazz) {
super(name,age,gender);//我有使用super复用Person类的相关有参构造函数!
this.stuNo = stuNo;
this.clazz = clazz;
}
@Override
public String toString() {
return super.toString()+"-" +stuNo+ "-" +clazz;
}
@Override
public int hashCode() { //别慌,下面有解释这是什么
final int prime = 31;
int result = 1;
result = prime * result + ((clazz == null) ? 0 : clazz.hashCode());
result = prime * result + ((stuNo == null) ? 0 : stuNo.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (clazz == null) {
if (other.clazz != null)
return false;
} else if (!clazz.equals(other.clazz))
return false;
if (stuNo == null) {
if (other.stuNo != null)
return false;
} else if (!stuNo.equals(other.stuNo))
return false;
return true;
}
}
Q:哇好厉害啊!hashCode()
是什么东西啊!equals()
写得好精妙啊!
A:关于这个hashCode()
啊。一般来说他和equals()
在覆写的时候都是要一起覆写的
那么这里的这个hashCode()
啊,他也不是我写的,他是VScode自动生成的...我也不知道他在干什么。
Q:那equals()
呢!这写的逻辑有点精妙啊!
A:那么很巧的是equals()
也是自动生成的。You see see,作为一个成熟的编辑器,要学会主动帮用户写代码啊!
Q:哇怎么才能让VScode帮我写代码呢!
A:让你看文章不认真!在开头!VScode教程!
Q:啊...自动生成?那不会出什么错吗!我记得题目对equals()
有特殊要求的啊!
A:VScode真的是很厉害的啊,自动生成的代码我也是看过的,完全符合题目的特殊要求,可以说是文不加点啊!
恭喜,至此,Student类已经写完了!
Company类
题目要求:
Company类属性:
String name
真的很简短有没有...
实际代码也很简单:
class Company{
private String name;
题目要求:
Company类方法:
public Company(String name); public String toString(); //直接返回name public boolean equals(Object obj);//name相同返回true
这个类是如此的短,以至于我怀疑他是来搞笑的
实际代码:
public Company(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
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;
Company other = (Company) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
你别看长,全是VScode写的,跟我没关系
恭喜,至此,Company类已经写完了!
Employee类
题目要求:
Employee类继承自
Person
,属性:Company company, double salary
这个简单!
实际代码:
class Employee extends Person{
Company company;
double salary;
可以看到上面来搞笑的Company类派上用场了!
题目要求:
Employee类方法:
//建议使用super复用Person类的相关有参构造函数 public Employee(String name, int age, boolean gender, double salary, Company company); public String toString(); //返回"Employee:person的toString-company-salary"格式的字符串 public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true。再比较company与salary。 //比较salary属性时,使用DecimalFormat df = new DecimalFormat("#.#");保留1位小数
这里有个新需求
//比较salary属性时,使用DecimalFormat df = new DecimalFormat("#.#");保留1位小数
这个新需求是比较简单的,我在代码中给了注释,应该可以轻松理解
诶!别急着开写!题目还没完,题目突然给出了一段特殊的提醒!
编写equals方法重要说明:
- 对Employee的company属性的比较。要考虑传入为
null
的情况。如果company不为null且传入为null,返回false- 对所有String字符类型比较时,也要考虑
null
情况。
害,别提醒了,牛逼轰轰的VScode都已经考虑到了!
以下为基本由VScode编写的实际代码,
public Employee(String name, int age, boolean gender, Company company, double salary) {
super(name, age, gender);
this.company = company;
this.salary = salary;
}
@Override
public String toString() {
return super.toString()+"-"+company + "-" + salary;
}
@Override
public int hashCode() {//
final int prime = 31;
int result = 1;
result = prime * result + ((company == null) ? 0 : company.hashCode());
long temp;
temp = Double.doubleToLongBits(salary);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
//下面这句是题目的新需求
//其作用是让变量df变成无情的格式化机器
DecimalFormat df = new DecimalFormat("#.#");
if (company == null) {
if (other.company != null)
return false;
} else if (!company.equals(other.company))
return false;
//有请无情的格式化机器df出场!
//df.format可以格式化数字,让他保留一位小数
if (!df.format(salary).equals(df.format(other.salary)))
return false;
return true;
}
}
恭喜,至此,四个类都已经写完了!
此时!题目给出了温馨提示
提示
- 排序可使用
Collections.sort
equals
方法要考虑周全
啊!好!说得好!不愧是你!
1.我们在Person类里写的接口和接口配套的compareTo()
方法就是为了排序的时候用Collections.sort
的!
2.equals
方法?没有人能比VScode考虑得还周全的!
此时!题目给出了
main方法说明
嘿嘿,终于要开始写主函数了啊!来!我们首先把main写出来!并且定义一堆乱七八糟的变量,以备不时之需
以下为代码:
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
String command,name,stuNo,clazz,tem;
int age,s=0,e=0;
double salary;
boolean gender,flag;
Company company;
题目开始提要求了!
创建若干Student对象、Employee对象。
输入s
,然后依次输入name age gender stuNo clazz
创建Student对象。
输入e
,然后依次输入name age gender salary company
创建Employee对象。
然后将创建好的对象放入List personList
。输入其他字符,则结束创建。
创建说明:对于String类型,如果为null
则不创建对象,而赋值为null
。对于company属性,如果为null则赋值为null
,否则创建相应的Company对象。
对这个创建说明我要说两句啊,你看看这个
创建说明:对于String类型,如果为
null
则不创建对象,而赋值为null
。
这句呢...我写代码的时候没理他,然后事实上是能通过的
毕竟这个判题系统他看的是输出结果啊,System.out.println()
一写,不论是null还是"null",打印出来的话都是一样的
以下是代码:
List<Student> stuList=new ArrayList<>();
List<Employee> empList=new ArrayList<>();
List<Person> personList=new ArrayList<>();
//我们创建三个列表,分别存放Student对象、Employee对象、以及所有对象
command= sc.next();//下一条命令是什么!!
while(true){
if(command.equals("s")){ //是s!
name=sc.next();//我真的没理他
age=sc.nextInt();
gender=sc.nextBoolean();
stuNo=sc.next();
clazz=sc.next();
personList.add(new Student(name,age,gender,stuNo,clazz));
}
else if(command.equals("e")){ //是e!
name=sc.next();//我真的真的没理他
age=sc.nextInt();
gender=sc.nextBoolean();
salary=Double.parseDouble(sc.next());
tem = sc.next();//tem是临时变量!
if(tem==null)//用来判断输入的是不是null!
company=null;
else
company=new Company(tem);
personList.add(new Employee(name,age,gender, company, salary));
}
对personList中的元素实现先按照姓名升序排序,姓名相同再按照年龄升序排序。提示:可使用
Comparable
或Comparator
对于这个我要说两句。这一步题目要求排序,但是实际上呢,题目还要求我们输出,只不过没说而已,让我们自己体会。迷惑啊...
我一直以为他只要排序不用输出的...结果就是我被这一句坑害了起码40分钟!一直说我答案错误!!呜呜呜
以下是代码:
else{ //如果输入的命令是其他字符
//下面这句是排序,其实现全靠前面的Person接口定义
Collections.sort(personList);
for(Person i:personList){ //遍历personList
System.out.println(i.getClass().getName()+":"+i);
}
break;//输入了其他字符就结束创建
}
//下面这句在if语句外。在做完if判断后,重新读取新的命令开始下一个循环
command=sc.next();
Q:卧槽,你这for写的啥玩意!
A:这是java的for
循环的另一种用法,具体用法如下:for(类型 变量:可数项) {代码块}
你会发现for(Person i:personList)
他接近于Python的 for i in personList
,只不过java规定变量在使用前就要确定类型,所以i
前面会加Person
以确定i
是Person
类。Python里的in
,java用一个封号代替,可以看出不同语言间还是有很大的相似性的
接受输入,如果输入为
exit
则return
退出程序,否则继续下面步骤。
他真的很奸诈啊,这句话隐含了一个条件:要做一个while(true)
的死循环
也就是说,如果输入为exit
则退出程序,否则,如果是其他的输入,就不断重复下面步骤
代码如下:
while(true){
command=sc.next();
if(command.equals("exit"))
return;
else{
将personList中的元素按照类型分别放到stuList与empList。注意:不要将两个内容相同的对象放入列表(是否相同是根据equals返回结果进行判定)。
这里的难点在于不要将两个内容相同的对象放入列表
这需要我们在将每一个新的对象放进去的时候做一个遍历,看看之前的数组里有没有一样的。那么如果你是顺着做过来的话呢,你会发现这个要求是上一题的核心要求。
具体代码如下:
for(Person i:personList){//遍历personList列表
flag=true; //用flag来表示到底有没有重复的
if (i.getClass()==Student.class){//如果是Student类
//j是循环变量,s则表示目前有多少个Student类
for(int j=0;j<s;j++){
if (stuList.get(j).equals(i)) {//不妙,有重复
flag=false;
}
}
if (flag==true){
stuList.add((Student) i); //妙啊,这个是没有重复的
s++;
}
}
else if (i.getClass()==Employee.class){//如果是Employee类
for(int j=0;j<e;j++){ //以下同上
if (empList.get(j).equals(i)) {
flag=false;
}
}
if (flag==true){
empList.add( (Employee) i);
e++;
}
}
}
输出字符串
stuList
,然后输出stuList中的每个对象。
这段代码难度之低难以想象!
System.out.println("stuList");
for (Student j : stuList) {
System.out.println("Student:"+j);
}
输出字符串
empList
,然后输出empList中的每个对象。
u1s1,这段也是!
System.out.println("empList");
for (Employee j : empList) {
System.out.println("Employee:"+j);
}
}
}
}
}
你可以看见啊,最后这个大括号都是阶梯状的,可见我这个代码缩进做的还是很可以的啊!
题目温馨提示:
1-3
为一个测试点4-6
为一个测试点
然后是题目给出的输入输出样例啊
输入样例:
s zhang 23 false 001 net15 e wang 18 true 3000.51 IBM s zhang 23 false 001 net15 e bo 25 true 5000.51 IBM e bo 25 true 5000.52 IBM e bo 18 true 5000.54 IBM e tan 25 true 5000.56 IBM e tan 25 true 5000.51 IBM s wang 17 false 002 null s wang 17 false 002 null e hua 16 false 1000 null s wang 17 false 002 net16 e hua 16 false 1000 null e hua 18 false 1234 MicroSoft ! continue
输出样例:
Employee:bo-18-true-IBM-5000.54 Employee:bo-25-true-IBM-5000.51 Employee:bo-25-true-IBM-5000.52 Employee:hua-16-false-null-1000.0 Employee:hua-16-false-null-1000.0 Employee:hua-18-false-MicroSoft-1234.0 Employee:tan-25-true-IBM-5000.56 Employee:tan-25-true-IBM-5000.51 Student:wang-17-false-002-null Student:wang-17-false-002-null Student:wang-17-false-002-net16 Employee:wang-18-true-IBM-3000.51 Student:zhang-23-false-001-net15 Student:zhang-23-false-001-net15 stuList Student:wang-17-false-002-null Student:wang-17-false-002-net16 Student:zhang-23-false-001-net15 empList Employee:bo-18-true-IBM-5000.54 Employee:bo-25-true-IBM-5000.51 Employee:hua-16-false-null-1000.0 Employee:hua-18-false-MicroSoft-1234.0 Employee:tan-25-true-IBM-5000.56 Employee:tan-25-true-IBM-5000.51 Employee:wang-18-true-IBM-3000.51
如有任何对代码的问题请qq联系:453986082