PTA题目集7-9的总结
前言
PTA题目集7
知识点主要有类的继承、多态性使用方法以及接口的应用,ArrayList链表里面的排序,如何保留两位小数。题量2道,题量适中,难度适中。
PTA题目集8
知识点主要是类的设计,字符串比较,如何保留两位小数,判断各个类之间的关系。题量1道,题量适中,难度是这3次中作业中最难的,需要自己进行类设计。
PTA题目集9
知识点主要还是类的设计,字符串比较,如何通过类与类之间的关系得到对应的信息,题量1道,题量适中,因为是迭代上一次的代码,难度相对于上次简单一点。
设计与分析
题目集7的7-1
Source Monitor生成图内容

Power Designer类图

题目集7的7-2
Source Monitor生成图内容

Power Designer类图

1.题目集7(7-1)、(7-2)两道题目的递进式设计分析总结
7-1设计分析:
(1)Trapezoid类,Circle类,Rectangle类,Triangle类继承Shape类,Shape类里面的方法主要写判断数据是否合法和计算面积的方法;
(2)每一个类的各个属性设置为私有的,进行封装,通过set,get方法对其进行改变和获取,提高了代码的可用性和可维护性。
(3)Card类与Shape类是关联关系,shape作为Card类的属性;
(4)DealCardList类与Card类是关联关系;
(5)Card类继承Comparable接口,大小排序可以运用CompareTo()方法;
小细节:在Main类中定义一个静态Scanner对象,这样在其它类中如果想要使用该对象进行输入,则直接
使用Main.input.next…即可(避免采坑)
7-2设计分析
(1)在上一题的代码上进行迭代
(2)这一次与上一次的区别在于需要按照不同形状进行分类以及排序,每一个[]里面输出相同类型的图形,最后求出不同形状总值的最大值;
(3)每一个形状的数值加到同一个链表里,这样能对同一种形状里面的面积进行排序,并且求出每一个链表面里总和的最大值,最好输出该值。
class DealCardList{
ArrayList<Card> cardList=new ArrayList<>();
ArrayList<Card> cardList1=new ArrayList<>();
ArrayList<Card> cardList2=new ArrayList<>();
ArrayList<Card> cardList3=new ArrayList<>();
ArrayList<Card> cardList4=new ArrayList<>();
总结:
对于每一次的输出都是一样的,所以可以写一个方法,并用迭代器遍历,可以减少很多重复代码
public void show(ArrayList<Card> list) {
Iterator<Card> itr = list.iterator();
System.out.print("[");
while(itr.hasNext()) {
Card tCard = itr.next();
Shape tShape = tCard.getShape();
System.out.print(tShape.getShapeName() + ":");
String str = String.format("%.2f",tShape.getArea());
System.out.print(str + " ");
}
System.out.print("]");
}
需要输出的时候调用它,可以使代码的复用性更强,代码更加简便。
对每一个链表里的面积进行排序:
public void cardSort(ArrayList<Card> list) {
for(int j = 0;j < list.size();j++) {
for(int k = j+1;k < list.size();k++) {
double area1 = list.get(j).getShape().getArea();
double area2 = list.get(k).getShape().getArea();
if(area1 < area2) {
Collections.swap(list, k, j);
}
}
}
}
四个数之间的比较
double max1 = (sum1>=sum2)?sum1:sum2;
double max2 = (sum3>=sum4)?sum3:sum4;
double max;
if(max1>=max2)
max=max1;
else
max=max2;
return max;
根据需求找到相同点来解决问题。
题目集8
Source Monitor生成图内容

Power Designer类图

题目集9
Source Monitor生成图内容

Power Designer类图

题目集8和题目集9两道ATM机仿真题目的设计思路分析总结
题目集8的设计思路分析
(1)创不同的新类实现初始化;
(2)明确需要初始化的信息,找到他们之间的联系;
(3)该题目需要初始化 用户姓名 隶属银行 银行账号 初始余额 隶属卡号
Person类的属性:AccountList,name
通过Person类的有参构造方法可以将用户姓名与银行账号对应起来;
BankAccount类的属性:number,cardList,money
通过BankAccount类的有参构造方法可以将隶属卡号与初始余额以及银行账号对应起来;
Bank类的属性的属性:personList,accountList,name,ATMList
通过Bank类的有参构造方法可以将ATM机的编号,银行名字,银行账户,用户连接起来;
完成以上信息的初始化;
功能实现
(1)卡号是否存在(通过银行---->账户---->卡与输入的卡号进行比较)
public boolean Com1(String cardno) {
for(int i = 0;i < listBank.size();i++) {
ArrayList<BankAccount> listAccount = listBank.get(i).getAccountList();
for(int j =0;j < listAccount.size();j++) {
ArrayList<Card> listCard = listAccount.get(j).getCardList();
for(int k = 0;k < listCard.size();k++) {
if(cardno.equals(listCard.get(k).getCardNo()))
return true;
}
}
}
return false;
}
(2) ATM机的编号是否存在(通过银行---->ATM机的编号与输入的ATM机编号进行比较)
public boolean Com2(String ATMNO) {
for(int i = 0;i < listBank.size();i++) {
ArrayList<ATM> listATM = listBank.get(i).getATMList();
for(int j = 0;j < listATM.size();j++) {
if(ATMNO.equals(listATM.get(j).getNumber()))
return true;
}
}
return false;
}
(3)银行卡密码是否正确
法一:所有卡的密码都是88888888,直接拿输入的密码与88888888进行比较
法二(通过银行---->账户---->ATM机的密码与输入的ATM机的密码进行比较):
public boolean Com3(String cardNum,String password) {
for(int i = 0;i < listBank.size();i++) {
ArrayList<BankAccount> listAccount = listBank.get(i).getAccountList();
for(int j =0;j < listAccount.size();j++) {
ArrayList<Card> listCard = listAccount.get(j).getCardList();
for(int k = 0;k < listCard.size();k++) {
if(listCard.get(k).getPassword().equals(password))
return true;
}
}
}
return false;
}
(4)输入取款金额是否大于账户余额
public boolean Com4(String cardNum,double money) {
BankAccount tAccount = null;
for(int i = 0;i < listBank.size();i++) {
ArrayList<BankAccount> listAccount = listBank.get(i).getAccountList();
for(int j =0;j < listAccount.size();j++) {
ArrayList<Card> listCard = listAccount.get(j).getCardList();
for(int k = 0;k < listCard.size();k++) {
if(listCard.get(k).getCardNo().equals(cardNum))
System.out.print("");
tAccount = listAccount.get(j);
}
if(money>tAccount.getMoney())
return true;
}
}
return false;
}
(5)是否是跨行取款
public boolean Com5(String cardNum,String ATMNum) {
Bank tBank1 = null;
for(int i = 0;i < listBank.size();i++) {
ArrayList<ATM> listATM = listBank.get(i).getATMList();
for(int j = 0;j < listATM.size();j++) {
if(listATM.get(j).getNumber().equals(ATMNum))
tBank1 = listBank.get(i);
}
}
if(getBank(getAccount(cardNum)).equals(tBank1))
return true;
return false;
}
(6)写一个方法输出结果:
public void showResult() {
String[] str = str1.split("\\s+");
String str2 = str[0]; //卡号
String str3 = str[1];//密码
String str4 = str[2];//ATM机编号
double str5 = Double.parseDouble(str[3]);//金额
if(Com1(str2)==false) {
System.out.println("Sorry,this card does not exist.");
}else if(Com2(str4)==false) {
System.out.println("Sorry,the ATM's id is wrong.");
}else if(Com3(str2, str3)==false) {
System.out.println("Sorry,your password is wrong.");
}else if(Com4(str2, str5)==true) {
System.out.println("Sorry,your account balance is insufficient.");
}else if(Com5(str2,str4)==false)
System.out.println("Sorry,cross-bank withdrawal is not supported.");
else if(str5>0) {
System.out.println((getPerson(getAccount(str2)).getName()+"在"+(getBank(getAccount(str2)).getName())+"的"+str4+"号ATM机"+"上取款¥"+String.format("%.2f",str5)));
System.out.println("当前余额为¥"+String.format("%.2f",getAccount(str2).getMoney()-str5));
getAccount(str2).setMoney((getAccount(str2).getMoney()-str5));
}
else if(str5<0) {
System.out.println((getPerson(getAccount(str2)).getName()+"在"+(getBank(getAccount(str2)).getName())+"的"+str4+"号ATM机"+"上存款¥"+String.format("%.2f",(-str5))));
System.out.println("当前余额为¥"+String.format("%.2f",getAccount(str2).getMoney()-str5));
getAccount(str2).setMoney((getAccount(str2).getMoney()-str5));
}
}
步骤总结:
1.通过初始化知道所有的信息都能在银行通过一层层得到,所以在这个类需要传入银行链表以及输入的内容;
2.5种错误情况的判断;
3.通过循环得到各个类里面的属性;
4.输出结果的方法;
题目集9的设计思路分析
在老师代码上进行迭代
从老师的代码中可以看到很明显的对应关系
UnoinPay类里面有银行链表;
Bank类里面有账户链表,银行卡链表;
Account类里面有银行卡链表
银联与银行是关联关系(1对多)
银行与账户是关联关系(1对多)
用户与账户是关联关系(1对多)
账户与银行卡是关联关系(1对多)
银行与ATM是关联关系(1对多)
题目改变的地方:
1.银行账户分为借记账户和贷记账户两种,其中,借记账户不能够透支取款,而贷记账户可以透支取款(可能需要支付手续费)。
2.根据账户 的不同,银行卡一般分为借记卡(针对借记账户)和信用卡(针对贷记账户) 两类。
3.本次作业中银行卡包含借记卡和信用卡两类,且允许跨行办理相关业务,在中国建设银行上跨行取款利率:2%,在中国工商银行上跨行取款利率:3%,在中国农业银行上跨行取款利率:4%,贷记取款的利率是取款金额的 5% ,最大限额为50000 元
实际改进:
1.在bank类里的属性加上rate;
2.在有参构造函数中加上rate,并在初始化里面附上利率值
Bank ccb = new Bank("1001","中国建设银行",0.02);
Bank icbc = new Bank("1002","中国工商银行",0.03);
Bank ibbc = new Bank("1003","中国农业银行",0.04);
3.并对原没有的信息进行初始化;
4.现在存在贷记账户,输出余额不足时需要判断是什么类型的账户
/**
* 校验取款金额是否大于余额
*/
if (amount > balance-amount*aTM.getBank().getRate()&&account.getBankKind().equals("借记账号")) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
if (amount+amount*aTM.getBank().getRate()-balance*0.05 > balance+50000&&account.getBankKind().equals("贷记账号")&&balance<=0) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
if (amount+amount*aTM.getBank().getRate()-(amount - balance)*0.05 > balance+50000&&account.getBankKind().equals("贷记账号")&&balance>0) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
5.根据是否跨行,是否是借记账户,是否为贷记账户分成4种情况进行计算:
/**
* 跨行以及借记
*/
if (account.getBank().getBankNO() != aTM.getBank().getBankNO()&&account.getBankKind().equals("借记账号")) {
account.setBalance(balance - amount-amount*aTM.getBank().getRate());
}
/**
* 不跨行以及借记
*/
if (account.getBank().getBankNO() == aTM.getBank().getBankNO()&&account.getBankKind().equals("借记账号")) {
account.setBalance(balance - amount);
}
/**
* 不跨行以及贷记
*/
if (account.getBank().getBankNO() == aTM.getBank().getBankNO()&&account.getBankKind().equals("贷记账号")) {
if(balance>=amount) {
account.setBalance(balance - amount);
}else if(amount>balance&&balance>0) {
account.setBalance(balance - amount - (amount - balance)*0.05);
}else if(amount>balance&&balance<=0) {
account.setBalance(balance - amount - amount *0.05);
}
}
/**
* 跨行以及贷记
*/
if (account.getBank().getBankNO() != aTM.getBank().getBankNO()&&account.getBankKind().equals("贷记账号")) {
if(balance>=amount) {
account.setBalance(balance - amount - amount*aTM.getBank().getRate());
}else if(amount>balance&&balance>0) {
account.setBalance(balance - amount - (amount - balance)*0.05-amount*aTM.getBank().getRate());
}else if(amount>balance&&balance<=0) {
account.setBalance(balance - amount - amount *0.05-amount*aTM.getBank().getRate());
}
}
采抗心得
题目集7-2
问题:1.重复的方法写了太多遍了导致代码太长,使代码提交不了,方法总结的不到位;
总结:对于重复出现的代码,不要因为传入的参数不同而重复写多个方法,一定要写成一个方法,在需要的时候进行调用,改变参数就行。
问题:2.在判断的时候输入数据不合法,输出"Wrong Format"后,还会输出结果;
总结:当输入的数据不合法时,不输出结果,直接输出"Wrong Format";
改进:
if(num < 0 || num > 4){
System.out.println("Wrong Format");
System.exit(0);
}
if(dealCardList.validate()==false){
System.out.println("Wrong Format");
System.exit(0);
}
题目集8
问题:1.对类设计设计的不好,导致有一些功能无法实现,没有注意到查询余额与存,取款的输出不同;
总结:对与特殊的查询可以写过另一个方法进行输出
while(!str.equals("#")){
Agent agent = new Agent(listBank,str);
if(str.length()>20) {
agent.showResult();
}else
agent.showResult1();
str = in.nextLine();
}
public void showResult1() {
String[] str = str1.split("\\s+");
String str2 = str[0]; //卡号
System.out.println("¥"+String.format("%.2f",getAccount(str2).getMoney()));
}
问题:2.对一张卡连续存(取)款时,不会接着上一次存(取)款后的金额进行存(取)款;
改进:在每一次输出当前余额时后,改变Account上面的余额;
if(str5>0) {
System.out.println((getPerson(getAccount(str2)).getName()+"在"+(getBank(getAccount(str2)).getName())+"的"+str4+"号ATM机"+"上取款¥"+String.format("%.2f",str5)));
System.out.println("当前余额为¥"+String.format("%.2f",getAccount(str2).getMoney()-str5));
getAccount(str2).setMoney((getAccount(str2).getMoney()-str5));
}
else if(str5<0) {
System.out.println((getPerson(getAccount(str2)).getName()+"在"+(getBank(getAccount(str2)).getName())+"的"+str4+"号ATM机"+"上存款¥"+String.format("%.2f",(-str5))));
System.out.println("当前余额为¥"+String.format("%.2f",getAccount(str2).getMoney()-str5));
getAccount(str2).setMoney((getAccount(str2).getMoney()-str5));
}
题目集9
问题:1.对于借记账户取款时10000是包括手续费的,如果是跨行取款取10000是取不出来的
改进:对于借记账户需要在原有本金的基础上减去利息在与要去的钱作比较,如果要取得钱大于本金减去利息则输出"Sorry,your account balance is insufficient."
if (amount > balance-amount*aTM.getBank().getRate()&&account.getBankKind().equals("借记账号")) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
问题:2.对于贷记账号的最高额度是没有包括手续费的,对于取60000也是可以取出来的;
改进:对于贷记账户的透支利息可在要取的钱的基础上减去,如果最后算出的钱大于最初的10000加上贷记的50000则输出"Sorry,your account balance is insufficient."
if (amount+amount*aTM.getBank().getRate()-balance*0.05 > balance+50000&&account.getBankKind().equals("贷记账号")&&balance<=0) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
if (amount+amount*aTM.getBank().getRate()-(amount - balance)*0.05 > balance+50000&&account.getBankKind().equals("贷记账号")&&balance>0) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
改进建议
1.对于题目集7,8中得圈复杂度均在10一下,但题目集9的复杂度是32,加了很多if-else进行判断,下次写代码需注意这类情况,要不代码的可读性会很差;
2.题目集8,9两道ATM机的设计,第一次是自己写的类设计发现自己的初始化非常的麻烦,没有找到合适的方法,重复的代码过多,看了老师的代码后发现初始化非常的简单,找到每一个类之间的关系,一起初始化;
总结
字符串的比较
判断两个字符串是否相等用.equals,不要习惯性的==。
链表的返回值
链表的返回值是地址
equals方法的重写
在没有重写equals方法之前,类与类之间的比较是比较地址是否相同
数值保留两位小数
String.format
eg:String.format("%.2f ",getArea());
链表作为参数的传参方法
1.ArrayList<Integer> list = new ArrayList<Integer>();
public DealCardList(ArrayList<Integer> list) {
}
2.ArrayList<Card> cardList=new ArrayList<>();
public void cardSort(ArrayList<Card> list) {
}
对于类设计的心得
1.通过题目确定各个类的属性以及方法;
2.属性:
考虑该东西有什么特性,一对多用链表;
3.方法:
构造方法:有参构造方法和无参构造方法;
有了构造方法才可以在其他类里面new该类
一般方法:实现功能用的;
4.每个类里的方法只对类属性进行操作;
5.明确类与类之间的关系;
迭代器的使用
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
题目集7用到了关联关系
举例
A关联B(B是A的属性)老师与学生关系
A{
B b;
getB setB
}
java中其他类型的总结
1.A依赖B(System.out)
A{
方法a(B b){
}
}
2.A聚合B(B是A的属性)
A{
B b;
//构造函数中
A(B b){
this.b = b;
}
}
3.A组合B(B是A的属性)
A{
B b;
//构造函数中
A(){
this.b = new B () ;
}
}
心得体会
通过这次ATM机的类设计,慢慢的贴近现实生活,在类设计之前也会考虑很多现实生活中的问题,慢慢的感觉java对做大工程的用处很大,做出来的感觉非常的爽,希望自己能通过以后的学习,在慢慢发现java的美。

浙公网安备 33010602011771号