实验题目
项目分析
1.搭建项目框架
首先结合实验描述和第一点的编码要求,搭建框架。
分析可知,首先需要搭建的是Record
类,然后确定其中的成员变量的属性,结合图表可知,时间最好是作为一个单独的类Time
存在,然后金额以double
或者int
类型存在,说明以String
类型存在,然后就搭建好了,Record
类与Time
类的框架。
class Time{
// 最好成员设置为私有 然后设置对应的get set方法这样更符合面相对象的封装思想
public int month; // 月
public int day; // 日
// 无参数构造方法 写无参构造方法的目的是为了更好的调用 这个类的功能方法
public Time(){}
// 有参构造方法
public Time(int month, int day){
this.month = month;
this.day = day;
}
}
// 使用类Record存储账单记录信息,包括:时间、交易说明和⾦额
class Record{
// 最好成员设置为私有 然后设置对应的get set方法这样更符合面相对象的封装思想
public Time time; // 时间
public String TranscationDescription; // 账目说明
public double money; // 资金
public boolean flag; // 是否被扔掉
// 无参数构造方法 写无参构造方法的目的是为了更好的调用 这个类的功能方法
public Record(){}
// 有参构造方法
public Record(Time time, String TranscationDescription, double money){
this.time = time;
this.TranscationDescription = TranscationDescription;
this.money = money;
this.flag = false;
}
}
这样就解决了第一问的需求。
2.项目方法的加入
结合2,3两点可以知晓,需要创建一个可以生成随机账目的方法,我们命名为Record [] RandomAccount()
,属于Record
的方法。
// 产生随机账单的方法
public Record [] RandomAccount(){
// 生产随机数种子
Random r = new Random();
// 定义随机数组 题目要求三组
Record [] records = new Record[3];
// 定义时间类 来生成随机时间
Time time = new Time().RandomTime();
for (int i = 0; i < 3; ++ i){
Time time0 = new Time().RandomTime(); // 生成随机时间
int money0 = new Record().RandomMoney(); // 生成随机金额
String TranscationDescription0;
// 如果金额>0那么就是收入 反之就是支出
if (money0 > 0) TranscationDescription0 = "收入" + i;
else TranscationDescription0 = "支出" + i;
// 给数组赋值
records[i] = new Record(time0, TranscationDescription0, money0);
}
return records;
}
对于Record [] RandomAccount()
方法,里面设计的时候需要添加其他方法来辅助完成,比如随机生成日期的RandomTime()
方法,这个方法属于Time
类。
// 生成随机日期值
public Time RandomTime(){
// 引入随机种子
Random r = new Random();
// 月份数组
int Months [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int month = Months[r.nextInt(12)]; // 在12个月里面选一个
int day; // 天数
// 生成随机天数
if (isBigMonth(month)){ // 如果是大月
day = r.nextInt(31) + 1; // 生成范围1~31
} else if (isSmallMonth(month)) { // 如果是小月
day = r.nextInt(30) + 1; // 生成范围1~30
} else { // 如果是特殊月份 2月
day = r.nextInt(28) + 1; // 生成范围1~28
}
return new Time(month, day);
}
对于该方法也需要一定的辅助方法,各个判断大小月份的方法。
// 判断是否为大月
public boolean isBigMonth(int month){
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) return true;
return false;
}
// 判断是否为小月
public boolean isSmallMonth(int month){
if (month == 4 || month == 6 || month == 11) return true;
return false;
}
此刻2,3点的需求就基本完成了。
然后看最后一点
分析4可知,这个方法的目的是返回差异数组。
我们设计为Record [] FindDifferentBills(Record[] r1, Record[] r2)
public Record [] FindDifferentBills(Record[] r1, Record[] r2){
int cnt = 0; // 记录不同的单子数
for (int i = 0; i < 3; ++ i){
for (int j = 0; j < 3; ++ j){
if (r1[i].flag == true || r2[j].flag == true) continue; // 如果比较的记录里面存在 已经需要离开的了
if (CheckRecord(r1[i], r2[j])) { // 如果两个记录金额相等
r1[i].flag = true; // 那么把这个单子置为true
r2[j].flag = true;
}
}
}
// 筛选出还是false的单子的数量
for (int i = 0; i < 3; ++ i){
if (r1[i].flag == false) cnt ++;
}
for (int i = 0; i < 3; ++ i){
if (r2[i].flag == false) cnt ++;
}
// System.out.println(cnt);
// 存储最后的结果 长度为cnt
Record [] DiffResults = new Record [cnt];
int cnt2 = 0;
// 筛选出还是false的单子
for (int i = 0; i < 3; ++ i){
if (r1[i].flag == false) DiffResults[cnt2 ++] = r1[i];
}
for (int i = 0; i < 3; ++ i){
if (r2[i].flag == false) DiffResults[cnt2 ++] = r2[i];
}
// 自定义排序方法 是的结果符合按日期顺序
Comparator cmp = new MyComparator();
Arrays.sort(DiffResults, cmp);
return DiffResults;
}
该方法说涉及的其他方法为Record
类的boolean CheckRecord(Record record1, Record record2),判断两个record是否相等。
// 对比账单方法
public boolean CheckRecord(Record record1, Record record2){
// 程序需要按照⾦额项对比,剔除匹配项并寻找所有差异项输出 // 这是根据题目的这句话设计的
if (record1.money == record2.money) return true;
return false;
}
到这里基本就把这个类设计完成了,最后再两个类中加上打印的方法,方便显示,基本就没有问题了。
3.测试类的编写
// 测试类
public class Main{
public static void main(String [] args){
// 银行账单
Record[] bankRecords = new Record().RandomAccount();
// for (int i = 0; i < 3; i++) {
// bankRecords[i].PrintRecord(bankRecords[i]);
// }
// 创建企业账单
Record[] companyRecords = new Record().RandomAccount();
// for (int i = 0; i < 3; i++) {
// companyRecords[i].PrintRecord(companyRecords[i]);
// }
Record [] DiffResults = new Record().FindDifferentBills(bankRecords, companyRecords);
// 最后的筛选结果
for (Record record : DiffResults){
record.PrintRecord(record);
}
}
}
4.汇总
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
// 多写注释是一个好习惯 很多大厂都有检查程序员写注释的比赛
// 辅助时间类
// 改日期以平年为例子
class Time{
// 最好成员设置为私有 然后设置对应的get set方法这样更符合面相对象的封装思想
public int month; // 月
public int day; // 日
// 无参数构造方法 写无参构造方法的目的是为了更好的调用 这个类的功能方法
public Time(){}
// 有参构造方法
public Time(int month, int day){
this.month = month;
this.day = day;
}
// 输出时间
public void PrintTime(){
System.out.print(this.month+"月" + this.day + "日");
}
// 判断是否为大月
public boolean isBigMonth(int month){
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) return true;
return false;
}
// 判断是否为小月
public boolean isSmallMonth(int month){
if (month == 4 || month == 6 || month == 11) return true;
return false;
}
// 生成随机日期值
public Time RandomTime(){
// 引入随机种子
Random r = new Random();
// 月份数组
int Months [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int month = Months[r.nextInt(12)]; // 在12个月里面选一个
int day; // 天数
// 生成随机天数
if (isBigMonth(month)){ // 如果是大月
day = r.nextInt(31) + 1; // 生成范围1~31
} else if (isSmallMonth(month)) { // 如果是小月
day = r.nextInt(30) + 1; // 生成范围1~30
} else { // 如果是特殊月份 2月
day = r.nextInt(28) + 1; // 生成范围1~28
}
return new Time(month, day);
}
// 对比两个时间先后的方法 如果前者小于后者的话 那么返回1 反之 -1如果一样返回0 这个为顺序
public int CompareTime(Time t1, Time t2){
int num;
if (t1.month < t2.month) num = -1;
else if (t1.month > t2.month) num = 1;
else
{
if (t1.day < t2.day) num = -1;
else if (t1.day > t2.day) num = 1;
else num = 0;
}
return num;
}
}
// 使用类Record存储账单记录信息,包括:时间、交易说明和⾦额
class Record{
// 最好成员设置为私有 然后设置对应的get set方法这样更符合面相对象的封装思想
public Time time; // 时间
public String TranscationDescription; // 账目说明
public double money; // 资金
public boolean flag; // 是否被扔掉
public Record(){}
// 有参构造方法
public Record(Time time, String TranscationDescription, double money){
this.time = time;
this.TranscationDescription = TranscationDescription;
this.money = money;
this.flag = false;
}
// 生成随机金额
public int RandomMoney(){
// 引入随机种子
Random r = new Random();
int money = r.nextInt(601) - 300; // 生成的范围是-300~300的金额
while(money == 0) money = r.nextInt(601) - 300; // 防止是生成的是0 没有什么意义这个数字 这里有一个强制类型转换int to double
return money;
}
// 产生随机账单的方法
public Record [] RandomAccount(){
// 生产随机数种子
Random r = new Random();
// 定义随机数组 题目要求三组
Record [] records = new Record[3];
// 定义时间类 来生成随机时间
Time time = new Time().RandomTime();
for (int i = 0; i < 3; ++ i){
Time time0 = new Time().RandomTime(); // 生成随机时间
int money0 = new Record().RandomMoney(); // 生成随机金额
String TranscationDescription0;
// 如果金额>0那么就是收入 反之就是支出
if (money0 > 0) TranscationDescription0 = "收入" + i;
else TranscationDescription0 = "支出" + i;
// 给数组赋值
records[i] = new Record(time0, TranscationDescription0, money0);
}
return records;
}
// 对比账单方法
public boolean CheckRecord(Record record1, Record record2){
// 程序需要按照⾦额项对比,剔除匹配项并寻找所有差异项输出 // 这是根据题目的这句话设计的
if (record1.money == record2.money) return true;
return false;
}
// 打印账单
public void PrintRecord(Record record){
// 打印时间
System.out.print("时间:");
record.time.PrintTime();
System.out.print(" 金额:" + record.money + " ");
System.out.println("说明:" + record.TranscationDescription);
}
// 寻找两个账单中不同的地方
public Record [] FindDifferentBills(Record[] r1, Record[] r2){
int cnt = 0; // 记录不同的单子数
for (int i = 0; i < 3; ++ i){
for (int j = 0; j < 3; ++ j){
if (r1[i].flag == true || r2[j].flag == true) continue; // 如果比较的记录里面存在 已经需要离开的了
if (CheckRecord(r1[i], r2[j])) { // 如果两个记录金额相等
r1[i].flag = true; // 那么把这个单子置为true
r2[j].flag = true;
}
}
}
// 筛选出还是false的单子的数量
for (int i = 0; i < 3; ++ i){
if (r1[i].flag == false) cnt ++;
}
for (int i = 0; i < 3; ++ i){
if (r2[i].flag == false) cnt ++;
}
// System.out.println(cnt);
// 存储最后的结果 长度为cnt
Record [] DiffResults = new Record [cnt];
int cnt2 = 0;
// 筛选出还是false的单子
for (int i = 0; i < 3; ++ i){
if (r1[i].flag == false) DiffResults[cnt2 ++] = r1[i];
}
for (int i = 0; i < 3; ++ i){
if (r2[i].flag == false) DiffResults[cnt2 ++] = r2[i];
}
// 自定义排序方法
Comparator cmp = new MyComparator();
Arrays.sort(DiffResults, cmp);
return DiffResults;
}
// 自定义排序接口 账单Record的排序方法为 Time的顺序
class MyComparator implements Comparator<Record> {
@Override
public int compare(Record o1, Record o2) {
int num = new Time().CompareTime(o1.time, o2.time);
return num;
}
}
}
// 测试类
public class Main{
public static void main(String [] args){
// 银行账单
Record[] bankRecords = new Record().RandomAccount();
// for (int i = 0; i < 3; i++) {
// bankRecords[i].PrintRecord(bankRecords[i]);
// }
// 创建企业账单
Record[] companyRecords = new Record().RandomAccount();
// for (int i = 0; i < 3; i++) {
// companyRecords[i].PrintRecord(companyRecords[i]);
// }
Record [] DiffResults = new Record().FindDifferentBills(bankRecords, companyRecords);
// 最后的筛选结果
for (Record record : DiffResults){
record.PrintRecord(record);
}
}
}
运行结果: