PTA大作业_阶段性总结
前言
小总结
第六次PTA作业开始了新的篇章—-电信计费系列,由于吸取了之前的教训,所以每次的作业都要考虑可拓展性,虽然这个系列也用到了正则表达式,但是有之前的铺垫,已经能从容面对了,总的来说,相对之前的作业而言,有了更多的思考,更深入的理解了OO。
设计与分析
多态测试
题目简述:
输入立方体或圆柱体的信息,输出所有图形的表面积之和、体积之和
代码
import java.util.Scanner;
public class Main {
public static int cnt;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s;
Container[] containers = new Container[1000];
cnt = in.nextInt();
for (int i = 0; i < cnt; i++) {
s = in.next();
if ("cube".equals(s)) {
containers[i] = new Cube(in.nextDouble());
} else {
containers[i] = new Cylinder(in.nextDouble(), in.nextDouble());
}
}
System.out.printf("%.2f\n", Container.sumofArea(containers));
System.out.printf("%.2f\n", Container.sumofVolume(containers));
}
}
interface Container {
double pi = 3.1415926;
double area();
double volume();
static double sumofArea(Container[] c) {
double sum = 0;
for (int i = 0; i < Main.cnt; i++) sum += c[i].area();
return sum;
}
static double sumofVolume(Container[] c) {
double sum = 0;
for (int i = 0; i < Main.cnt; i++) sum += c[i].volume();
return sum;
}
}
class Cylinder implements Container {
private final double radius;
private final double high;
public Cylinder(double radius, double high) {this.radius = radius;this.high = high;}
@Override
public double area() {return 2 * pi * radius * radius + high * 2.0 * pi * radius;}
@Override
public double volume() {return pi * radius * radius * high;}
}
class Cube implements Container {
private final double sideLength;
public Cube(double sideLength) {this.sideLength = sideLength;}
@Override
public double area() {return sideLength * sideLength * 6.0;}
@Override
public double volume() {return sideLength * sideLength * sideLength;}
}
分析
既然题目已经提醒要用多态了,那么就要考虑什么时候可以用到多态,很明显,题目有两种图形,但是输出却是两种图形数据的和
所以我们考虑有让两个图形都实现一个共同的Container
接口,使得Container
在遍历容器求和时,通过多态可以让两种图形分别报出自己的数据。
sdut-Collection-sort–C~K的班级(II)
题目简述:
输入若干学生信息,输出去重后的学生信息
代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
HashSet studs = new HashSet<>();
int t = in.nextInt();
for (int i = 0; i < t; i++) {
studs.add(new Stud(in.next(), in.next(), in.next(), in.next()));
}
System.out.println(studs.size());
ArrayList studsArr = new ArrayList<>(studs);
Collections.sort(studsArr);
for (Stud s : studsArr) System.out.println(s);
}
}
class Stud implements Comparable{
String id, name, age, sex;
public Stud(String id, String name, String age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public int hashCode() {return Integer.parseInt(id);}
@Override
public boolean equals(Object obj) {return id.equals(((Stud) obj).id);}
@Override
public String toString() {return id + " " + name + " " + age + " " + sex;}
@Override
public int compareTo(Stud o) {return Integer.compare(Integer.parseInt(id), Integer.parseInt(o.id));}
}
分析
说到 去重,很明显,可以用
HashSet
来完成
使用HashSet
需要重写hashCode()
和equals()
@Override
public int hashCode() {
return Integer.parseInt(id);
}
@Override
public boolean equals(Object obj) {
return id.equals(((Stud) obj).id);
}
由于每个学生的学号是唯一的,那么我们可以将学号作为每个学生的 HashCode
,那么equals也同理
题目还提到排序
这需要让学生的类实现 Comparable
接口,将 HashSet
放入到链表,然后调用 Collections.sort()
对链表进行排序后,遍历输出,便是有序的
编写一个类Shop(商店)、内部类InnerCoupons(内部购物券)
题目简述:
商店类有内部类购物券,商店有面额为100,50的购物券,输入牛奶箱数,输出使用什么购物券买牛奶,以及牛奶剩余
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Shop myshop = new Shop(in.nextInt(), 50, 100);
myshop.buy();
}
}
class Shop {
private int milkCount;
private InnerCoupons coupons50;
private InnerCoupons coupons100;
class InnerCoupons {
public int value;
public InnerCoupons(int value) {this.value = value;}
public void buy() {
System.out.println("使用了面值为" + value + "的购物券进行支付");
setMilkCount(getMilkCount() - value / 50);
System.out.println("牛奶还剩" + getMilkCount() + "箱");
}
}
public void buy(){
coupons50.buy();
coupons100.buy();
}
public Shop(int milkCount, int coupons50, int coupons100) {
this.milkCount = milkCount;
this.coupons50 = new InnerCoupons(coupons50);
this.coupons100 = new InnerCoupons(coupons100);
}
public int getMilkCount() {return milkCount;}
public void setMilkCount(int milkCount) {this.milkCount = milkCount;}
}
分析
题目要求用内部类,根据题目要求完成即可
动物发声模拟器(多态)
题目简述:
用多态输出猫、狗、山羊的类型以及叫声
代码
//动物发生模拟器. 请在下面的【】处添加代码。
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
Goat goat = new Goat();
speak(cat);
speak(dog);
speak(goat);
}
//定义静态方法speak()
public static void speak(Animal animal) {
System.out.print(animal.getAnimalClass() + "的叫声:");
animal.shout();
}
}
//定义抽象类Animal
abstract class Animal {
abstract String getAnimalClass();
abstract void shout();
}
//基于Animal类,定义猫类Cat,并重写两个抽象方法
class Cat extends Animal {
@Override
String getAnimalClass() {return "猫";}
@Override
void shout() {System.out.println("喵喵");}
}
//基于Animal类,定义狗类Dog,并重写两个抽象方法
class Dog extends Animal {
@Override
String getAnimalClass() {return "狗";}
@Override
void shout() {System.out.println("汪汪");}
}
//基于Animal类,定义山羊类Goat,并重写两个抽象方法
class Goat extends Animal {
@Override
String getAnimalClass() {return "山羊";}
@Override
void shout() {System.out.println("咩咩");}
}
分析
题目要求用到多态,根据题目提示完成即可
电信计费系列1、系列2-手机+座机计费、系列3-短信计费
题目简述:
输入若干用户和其通讯记录,输出用户话费余额
代码
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* Main程序入口
* 职责:输入数据,将正确的信息存入InputData,*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
HashSet userSet = new HashSet<>();
ArrayList communicationRecords = new ArrayList<>();
String Line;
do {
Line = in.nextLine();
if (Line.equals("")) continue;
if (Line.charAt(0) == 'u') {
String[] uData = InputFormat.input_u_Format(Line);
if (uData != null) userSet.add(new User(uData[1], uData[2].charAt(0) - '0'));
} else if (Line.charAt(0) == 't') {
CallRecord tempCallRecord = InputFormat.input_t_Format(Line);
if (tempCallRecord != null) communicationRecords.add(tempCallRecord);
} else if (Line.charAt(0) == 'm') {
String[] mData = InputFormat.input_m_Format(Line);
if (mData != null) communicationRecords.add(new MessageRecord(mData[0], mData[1], mData[2]));
}
} while (!"end".equals(Line));
ArrayList users = new ArrayList<>(userSet);
DataCentre dataCentre = new DataCentre(users, communicationRecords);
dataCentre.printUserCosts();
}
}
/*
* CommunicationRecord通讯记录
* 由主动用户与应答用户为基本,电话,短信等方式构成*/
abstract class CommunicationRecord {
String callingNumber, answerNumber;
public CommunicationRecord(String callingNumber, String answerNumber) {
this.callingNumber = callingNumber;
this.answerNumber = answerNumber;
}
public CommunicationRecord() {
}
public String getCallingNumber() {
return callingNumber;
}
public String getAnswerNumber() {
return answerNumber;
}
}
class LandlinePhoneCharging extends ChargeMode {
public LandlinePhoneCharging() {
getChargeRules().add(new LandPhoneInCityRule());
getChargeRules().add(new LandPhoneInProvinceRule());
getChargeRules().add(new LandPhoneInLandRule());
}
@Override
double calCost(UserRecords userRecords) {
double cost = 0;
for (ChargeRule chargeRule : getChargeRules())
cost += (chargeRule instanceof CallChargeRule) ? ((CallChargeRule) chargeRule).calCost(userRecords) : 0;
return cost;
}
@Override
double getMonthlyRent() {
return 20;
}
}
class PhoneMessage extends ChargeMode {
private double monthlyRent = 0;
public PhoneMessage() {
getChargeRules().add(new SendMessageRule());
}
@Override
double calCost(UserRecords userRecords) {
double cost = 0;
for (ChargeRule chargeRule : getChargeRules())
cost += (chargeRule instanceof SendMessageRule) ? ((SendMessageRule) chargeRule).calCost(userRecords) : 0;
return cost;
}
@Override
double getMonthlyRent() {
return monthlyRent;
}
}
class PhoneCharging extends ChargeMode {
private double monthlyRent = 15;
public PhoneCharging() {
getChargeRules().add(new PhoneInCityRule());
getChargeRules().add(new PhoneInProvinceRule());
getChargeRules().add(new PhoneInLandRule());
getChargeRules().add(new PhoneAnsInLandRule());
getChargeRules().add(new SendMessageRule());
}
@Override
double calCost(UserRecords userRecords) {
double cost = 0;
for (ChargeRule chargeRule : getChargeRules())
cost += (chargeRule instanceof CallChargeRule) ? ((CallChargeRule) chargeRule).calCost(userRecords) : (chargeRule instanceof SendMessageRule) ? ((SendMessageRule) chargeRule).calCost(userRecords) : 0;
return cost;
}
@Override
double getMonthlyRent() {
return monthlyRent;
}
}
class UserRecords {
private ArrayList callingInCityRecords = new ArrayList<>();
private ArrayList callingInProvinceRecords = new ArrayList<>();
private ArrayList callingInLandRecords = new ArrayList<>();
private ArrayList answerInCityRecords = new ArrayList<>();
private ArrayList answerInProvinceRecords = new ArrayList<>();
private ArrayList answerInLandRecords = new ArrayList<>();
private ArrayList sendMessageRecords = new ArrayList<>();
private ArrayList receiveMessageRecords = new ArrayList<>();
public ArrayList getCallingInCityRecords() {
return callingInCityRecords;
}
public ArrayList getCallingInProvinceRecords() {
return callingInProvinceRecords;
}
public ArrayList getCallingInLandRecords() {
return callingInLandRecords;
}
public ArrayList getAnswerInCityRecords() {
return answerInCityRecords;
}
public ArrayList getAnswerInProvinceRecords() {
return answerInProvinceRecords;
}
public ArrayList getAnswerInLandRecords() {
return answerInLandRecords;
}
public ArrayList getSendMessageRecords() {
return sendMessageRecords;
}
public ArrayList getReceiveMessageRecords() {
return receiveMessageRecords;
}
}
abstract class ChargeMode {
ArrayList chargeRules = new ArrayList<>();
abstract double calCost(UserRecords userRecords);
abstract double getMonthlyRent();
public ArrayList getChargeRules() {
return chargeRules;
}
}
class MessageRecord extends CommunicationRecord {
private String message;
public MessageRecord(String callingNumber, String answerNumber, String message) {
super(callingNumber, answerNumber);
this.message = message;
}
public boolean isSendUser(User user) {
return callingNumber.equals(user.getNumber());
}
public boolean isAnsUser(User user) {
return answerNumber.equals(user.getNumber());
}
public String getMessage() {
return message;
}
}
/*
* DataCentre
* 职责:将记录与用户匹配,存用户数据*/
class DataCentre {
private ArrayList users; //所有用户
private ArrayList communicationRecords; //所有记录
public DataCentre(ArrayList users, ArrayList communicationRecords) {
this.users = users;
this.communicationRecords = communicationRecords;
matchingRecords();
}
/*根据拨出号码匹配其记录*/
private void matchingRecords() {
for (User user : users) {
ArrayList communicationRecords = new ArrayList<>();
for (CommunicationRecord communicationRecord : this.communicationRecords) {
//所有拨的记录匹配到用户
if (communicationRecord instanceof CallRecord && (user.getNumber().equals(communicationRecord.getCallingNumber())))
communicationRecords.add(communicationRecord);
else if (communicationRecord instanceof MessageRecord)
communicationRecords.add(communicationRecord);
}
user.getCallRecords().addAll(communicationRecords);
}
for (User user : users) {
ArrayList communicationRecords = new ArrayList<>();
for (CommunicationRecord communicationRecord : this.communicationRecords) {
//所有接的记录匹配到用户
if (communicationRecord instanceof CallRecord && (user.getNumber().equals(communicationRecord.getAnswerNumber())))
communicationRecords.add(communicationRecord);
else if (communicationRecord instanceof MessageRecord)
communicationRecords.add(communicationRecord);
}
user.getAnsRecords().addAll(communicationRecords);
}
}
// 按序输出用户的当月费用
public void printUserCosts() {
Collections.sort(users);
for (User user : users) {
user.classifyRecords();
System.out.println(user);
}
}
}
/*
* ChargeRule计费规则类
* */
class ChargeRule {
}
class LandPhoneInCityRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double cost = 0;
for (CallRecord callRecord : userRecords.getCallingInCityRecords()) {
int a = callRecord.getSecMinus() / 60 + callRecord.getSecMinus() % 60 > 0 ? 1 : 0;
cost += placePerCost(callRecord) * a;
}
return cost;
}
public double placePerCost(CallRecord callRecord) {
String ansAddress = callRecord.getAnswerAddressAreaCode();
return InCity(ansAddress) ? 0.1 : InProvince(ansAddress) ? 0.3 : 0.6;
}
}
class LandPhoneInProvinceRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
return 0;
}
}
class LandPhoneInLandRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
return 0;
}
}
class PhoneInCityRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double cost = 0;
for (CallRecord callRecord : userRecords.getCallingInCityRecords()) {
int a = callRecord.getSecMinus() / 60 + callRecord.getSecMinus() % 60 > 0 ? 1 : 0;
cost += placePerCost(callRecord) * a;
}
return cost;
}
public double placePerCost(CallRecord callRecord) {
String ansAddress = callRecord.getAnswerAddressAreaCode();
return InCity(ansAddress) ? 0.1 : InProvince(ansAddress) ? 0.2 : 0.3;
}
}
class PhoneInProvinceRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double cost = 0;
for (CallRecord callRecord : userRecords.getCallingInProvinceRecords()) {
int a = callRecord.getSecMinus() / 60 + callRecord.getSecMinus() % 60 > 0 ? 1 : 0;
cost += placePerCost() * a;
}
return cost;
}
public double placePerCost() {
return 0.3;
}
}
class PhoneInLandRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double cost = 0;
for (CallRecord callRecord : userRecords.getCallingInLandRecords()) {
int a = callRecord.getSecMinus() / 60 + callRecord.getSecMinus() % 60 > 0 ? 1 : 0;
cost += placePerCost(callRecord) * a;
}
return cost;
}
public double placePerCost(CallRecord callRecord) {
return 0.6;
}
}
class PhoneAnsInLandRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double cost = 0;
for (CallRecord callRecord : userRecords.getAnswerInLandRecords()) {
int a = callRecord.getSecMinus() / 60 + callRecord.getSecMinus() % 60 > 0 ? 1 : 0;
cost += placePerCost(callRecord) * a;
}
return cost;
}
public double placePerCost(CallRecord callRecord) {
return 0.3;
}
}
class InputFormat {
public static String[] input_u_Format(String str) {
Matcher m = Pattern.compile("([ut])-([0-9]{11,12}) ([0-3])").matcher(str);//(u)-(0\\d{9,11}) ([0-2])
if (m.find()) {
// if (!numTypeLegal(m.group(2), m.group(3))) return null;
return new String[]{m.group(1), m.group(2), m.group(3)};
} else return null;
}
private static boolean numTypeLegal(String num, String type) {
if (num.charAt(0) == '0') return num.charAt(0) == type.charAt(0);
else if (num.charAt(0) == '1') return num.length() == 11 && (type.charAt(0) == '1' || type.charAt(0) == '2');
else return false;
}
public static CallRecord input_t_Format(String str) {
return (input_00_Format(str) != null) ? input_00_Format(str) : (input_01_Format(str) != null) ? input_01_Format(str) : (input_10_Format(str) != null) ? input_10_Format(str) : (input_11_Format(str) != null) ? input_11_Format(str) : null;
}
private static CallRecord input_00_Format(String str) {
if (!input_t00_RightFormat(str)) return null;
String[] nums = new String[2];
int numbSplit = str.indexOf(" ", str.indexOf(" ") + 1) + 1;
String Nums = str.substring(0, numbSplit);
Matcher m = Pattern.compile("([ut])-([0-9]{10,12}) ([0-9]{10,12}) ").matcher(Nums);
if (m.find()) {
nums[0] = m.group(2);
nums[1] = m.group(3);
} else return null;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
simpleDateFormat.setLenient(false);
int dateSplit = str.indexOf(" ", str.indexOf(" ", numbSplit) + 1);
String Time1 = str.substring(numbSplit, dateSplit);
String Time2 = str.substring(dateSplit + 1);
Date date1, date2;
try {
date1 = simpleDateFormat.parse(Time1);
date2 = simpleDateFormat.parse(Time2);
} catch (ParseException e) {
return null;
}
if (date1.compareTo(date2) > 0) return null;
return new CallRecord(nums[0], nums[1], date1, date2);
}
private static CallRecord input_01_Format(String str) {
if (!input_t01_RightFormat(str)) return null;
String[] nums = new String[3];
// int numbSplit = str.indexOf(" ", str.indexOf(" ") + 1) + 1;
int numbSplit = blankIdx(str, 3);
String Nums = str.substring(0, numbSplit);
Matcher m = Pattern.compile("([ut])-([0-9]{10,12}) ([0-9]{11,12}) (\\d+) ").matcher(Nums);
if (m.find()) {
nums[0] = m.group(2);
nums[1] = m.group(3);
nums[2] = m.group(4);
} else return null;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
simpleDateFormat.setLenient(false);
int dateSplit = str.indexOf(" ", str.indexOf(" ", numbSplit) + 1);
String Time1 = str.substring(numbSplit, dateSplit);
String Time2 = str.substring(dateSplit + 1);
Date date1, date2;
try {
date1 = simpleDateFormat.parse(Time1);
date2 = simpleDateFormat.parse(Time2);
} catch (ParseException e) {
return null;
}
// if (isDate(Time1) || isDate(Time2))return null;
if (date1.compareTo(date2) > 0) return null;
return new CallRecord(nums[0], nums[1], nums[2], date1, date2, 1);
}
private static CallRecord input_10_Format(String str) {
if (!input_t10_RightFormat(str)) return null;
String[] nums = new String[3];
// int numbSplit = str.indexOf(" ", str.indexOf(" ") + 1) + 1;
int numbSplit = blankIdx(str, 3);
String Nums = str.substring(0, numbSplit);
Matcher m = Pattern.compile("([ut])-([0-9]{11,12}) (\\d+) ([0-9]{10,12}) ").matcher(Nums);
if (m.find()) {
nums[0] = m.group(2);
nums[1] = m.group(3);
nums[2] = m.group(4);
} else return null;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
simpleDateFormat.setLenient(false);
int dateSplit = str.indexOf(" ", str.indexOf(" ", numbSplit) + 1);
String Time1 = str.substring(numbSplit, dateSplit);
String Time2 = str.substring(dateSplit + 1);
Date date1, date2;
try {
date1 = simpleDateFormat.parse(Time1);
date2 = simpleDateFormat.parse(Time2);
} catch (ParseException e) {
return null;
}
if (date1.compareTo(date2) > 0) return null;
return new CallRecord(nums[0], nums[1], nums[2], date1, date2, 2);
}
private static CallRecord input_11_Format(String str) {
if (!input_t11_RightFormat(str)) return null;
String[] nums = new String[4];
// int numbSplit = str.indexOf(" ", str.indexOf(" ") + 1) + 1;
int numbSplit = blankIdx(str, 4);
String Nums = str.substring(0, numbSplit);
Matcher m = Pattern.compile("([ut])-([0-9]{11,12}) (\\d+) ([0-9]{11,12}) (\\d+) ").matcher(Nums);
if (m.find()) {
nums[0] = m.group(2);
nums[1] = m.group(3);
nums[2] = m.group(4);
nums[3] = m.group(5);
} else return null;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
simpleDateFormat.setLenient(false);
int dateSplit = str.indexOf(" ", str.indexOf(" ", numbSplit) + 1);
String Time1 = str.substring(numbSplit, dateSplit);
String Time2 = str.substring(dateSplit + 1);
Date date1, date2;
try {
date1 = simpleDateFormat.parse(Time1);
date2 = simpleDateFormat.parse(Time2);
} catch (ParseException e) {
return null;
}
if (date1.compareTo(date2) > 0) return null;
return new CallRecord(nums[0], nums[1], nums[2], nums[3], date1, date2);
}
private static int blankIdx(String str, int cnt) {
for (int i = 0, t = 0; i < str.length(); i++) {
if (t == cnt) return i;
if (str.charAt(i) == ' ') t++;
}
return str.length();
}
public static String[] input_m_Format(String str) {
Matcher m = Pattern.compile("(m)-(1[0-9]{10}) (1[0-9]{10}) ([a-z 0-9,.]+)").matcher(str);
if (m.matches()) {
return new String[]{m.group(2), m.group(3), m.group(4)};
} else return null;
}
private static boolean input_t00_RightFormat(String str) {
return str.matches("t-0\\d{9,11} 0\\d{9,11}( [0-9]{4}\\.(([1-9])|(1[0-2]))\\.(([1-9])|(([1|2])[0-9])|30|31) ((([0|1])[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])){2}");
}
private static boolean input_t01_RightFormat(String str) {
return str.matches("t-0\\d{9,11} 1\\d{10} 0\\d{2,3}( [0-9]{4}\\.(([1-9])|(1[0-2]))\\.(([1-9])|(([1|2])[0-9])|30|31) ((([0|1])[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])){2}");
}
private static boolean input_t10_RightFormat(String str) {
return str.matches("t-1\\d{10} 0\\d{2,3} 0\\d{9,11}( [0-9]{4}\\.(([1-9])|(1[0-2]))\\.(([1-9])|(([1|2])[0-9])|30|31) ((([0|1])[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])){2}");
}
private static boolean input_t11_RightFormat(String str) {
return str.matches("t-1\\d{10} 0\\d{2,3} 1\\d{10} 0\\d{2,3}( [0-9]{4}\\.(([1-9])|(1[0-2]))\\.(([1-9])|(([1|2])[0-9])|30|31) ((([0|1])[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])){2}");
}
}
/*******************************************************************
* User调用通话记录和计费模式,
* 通话记录只将记录分类,整理,
* 计费模式是计费规则类的集合,计费规则只需将所有计费规则进行整理,统一计费
* 职责:将用户按终端、记录整合
* */
class User implements Comparable {
private UserRecords userRecords = new UserRecords();
private ArrayList callRecords = new ArrayList<>();
private ArrayList ansRecords = new ArrayList<>();
private double balance = 100;
private ChargeMode chargeMode;
private String number;
public User(String number, int mod) {
this.number = number;
switch (mod) {
case 0: {
chargeMode = new LandlinePhoneCharging();
break;
}
case 1: {
chargeMode = new PhoneCharging();
}
case 2: {
}
case 3: {
chargeMode = new PhoneMessage();
}
default:
}
}
// 话费
public double calCost() {
return chargeMode.calCost(userRecords);
}
// 余额
public double calBalance() {
return balance - chargeMode.getMonthlyRent();
}
/*将用户的所有记录分类,存于userRecords
* */
public void classifyRecords() {
//拨的
for (CommunicationRecord communicationRecord : callRecords) {
if (communicationRecord instanceof CallRecord) {
if (((CallRecord) communicationRecord).callInCity())
userRecords.getCallingInCityRecords().add((CallRecord) communicationRecord);
else if (((CallRecord) communicationRecord).callInProvince())
userRecords.getCallingInProvinceRecords().add((CallRecord) communicationRecord);
else if (((CallRecord) communicationRecord).callInLand())
userRecords.getCallingInLandRecords().add((CallRecord) communicationRecord);
} else if (communicationRecord instanceof MessageRecord) {
if (((MessageRecord) communicationRecord).isSendUser(this))
userRecords.getSendMessageRecords().add((MessageRecord) communicationRecord);
}
}
//接的
for (CommunicationRecord communicationRecord : ansRecords) {
if (communicationRecord instanceof CallRecord) {
if (((CallRecord) communicationRecord).ansInCity())
userRecords.getAnswerInCityRecords().add((CallRecord) communicationRecord);
else if (((CallRecord) communicationRecord).ansInProvince())
userRecords.getAnswerInProvinceRecords().add((CallRecord) communicationRecord);
else if (((CallRecord) communicationRecord).ansInLand())
userRecords.getAnswerInLandRecords().add((CallRecord) communicationRecord);
} else if (communicationRecord instanceof MessageRecord) {
if (((MessageRecord) communicationRecord).isAnsUser(this))
userRecords.getSendMessageRecords().add((MessageRecord) communicationRecord);
}
}
}
public UserRecords getUserRecords() {
return userRecords;
}
public String getNumber() {
return number;
}
public ArrayList getCallRecords() {
return callRecords;
}
public ArrayList getAnsRecords() {
return ansRecords;
}
@Override
public int compareTo(User o) {
return number.compareTo(o.getNumber());
}
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
return obj instanceof User && number.equals(((User) obj).number);
}
@Override
public String toString() {
double cost = calCost();
double balance = calBalance() - cost;
return getNumber() + " " + OutFormat.doubleFormat(cost) + " " + OutFormat.doubleFormat(balance);
}
}
class CallRecord extends CommunicationRecord {
private Date startTime, endTime;
private String callingAddressAreaCode, answerAddressAreaCode;
//座机互打
public CallRecord(String callingNumber, String answerNumber, Date startTime, Date endTime) {
super(callingNumber, answerNumber);
this.startTime = startTime;
this.endTime = endTime;
callingAddressAreaCode = callingNumber.substring(0, 4);
answerAddressAreaCode = answerNumber.substring(0, 4);
}
/* //座机打手机 1
public CallRecord(String callingNumber, String answerNumber, String answerAddressAreaCode, Date startTime, Date endTime) {
super(callingNumber, answerNumber);
this.startTime = startTime;
this.endTime = endTime;
callingAddressAreaCode = callingNumber.substring(0, 4);
this.answerAddressAreaCode = answerAddressAreaCode;
}
//手机打座机 2
public CallRecord(String callingNumber, String callingAddressAreaCode, String answerNumber, Date startTime, Date endTime) {
super(callingNumber, answerNumber);
this.startTime = startTime;
this.endTime = endTime;
this.callingAddressAreaCode = callingAddressAreaCode;
}*/
public CallRecord(String callingNumber, String callingAreaCode_Or_AnsNumber, String ansNumber_Or_AnsAreaCode, Date startTime, Date endTime, int mod) {
if (mod == 1) {
this.callingNumber = callingNumber;
this.answerNumber = callingAreaCode_Or_AnsNumber;
this.startTime = startTime;
this.endTime = endTime;
callingAddressAreaCode = callingNumber.substring(0, 4);
answerAddressAreaCode = ansNumber_Or_AnsAreaCode;
} else {
this.callingNumber = callingNumber;
this.answerNumber = ansNumber_Or_AnsAreaCode;
this.startTime = startTime;
this.endTime = endTime;
callingAddressAreaCode = callingAreaCode_Or_AnsNumber;
answerAddressAreaCode = ansNumber_Or_AnsAreaCode.substring(0, 4);
}
}
//手机互打
public CallRecord(String callingNumber, String callingAddressAreaCode, String answerNumber, String answerAddressAreaCode, Date startTime, Date endTime) {
super(callingNumber, answerNumber);
this.callingAddressAreaCode = callingAddressAreaCode;
this.answerAddressAreaCode = answerAddressAreaCode;
this.startTime = startTime;
this.endTime = endTime;
}
/*南昌市内拨打*/
public boolean callInCity() {
return "0791".equals(callingAddressAreaCode);
}
/*非市内的省内拨打*/
public boolean callInProvince() {
if (callInCity() || callingAddressAreaCode.length() < 3) return false;
if ("0701".equals(callingAddressAreaCode)) return true;
return "079".equals(callingAddressAreaCode.substring(0, 3)) && (callingAddressAreaCode.charAt(3) >= '0' && callingAddressAreaCode.charAt(3) = '0' && answerAddressAreaCode.charAt(3) = '0' && callingAddressAreaCode.charAt(3) 5) return 0.7 + (num - 5) * 0.3;
else if (num > 3) return 0.3 + (num - 3) * 0.2;
else return num * 0.1;
}
private int getMessageNum(MessageRecord messageRecord) {
int len = messageRecord.getMessage().length();
int res = len / 10 ;
res += len % 10 != 0 ? 1 : 0;
return res;
}
}
class OutFormat {
public static Double doubleFormat(double b) {
DecimalFormat df = new DecimalFormat("#.00");
return Double.valueOf(df.format(b));
}
}
代码类图
分析
个人的思路是将用户和记录读入后,分别存于容器,再将数据传到一个
DataCenter
的类,此类的职责是将所有通讯记录匹配到用户
之后在用户得到所有自己的通讯记录后,将其分类存于不同的容器,从而让不同的Rule
处理自己应处理的数据,分别计算费用并汇总;
其实还有比较简单的思路,那就是将用户和记录分别存于容器,遍历每个用户,让每个用户遍历所有通讯记录,找到自己的通讯记录并将其按类型计费汇总,很明显,这样写出的代码性能会很差,所以没有采用这样的思路;
踩坑心得
关于 HashSet
的使用
疑惑代码:
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
HashSet users = new HashSet<>();
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
for(User u : users) System.out.println(u);
}
}
class User{
String number;
//*********************************************************************************//
public User(String number) {
this.number = number;
}
}
输出:
User@5594a1b5
User@3b6eb2ec
User@3ac3fd8b
User@6a5fc7f7
User@1e643faf
进程已结束,退出代码0
很明显,他们虽然放到了 HashSet
中,但是 HashSet
并不认为他们是同一对象
给 User
重写了 hashCode()
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
HashSet users = new HashSet<>();
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
for(User u : users) System.out.println(u);
}
}
class User{
String number;
public User(String number) {
this.number = number;
}
@Override
public int hashCode() {
return Integer.parseInt(number);
}
}
输出
User@756b5b3
User@756b5b3
User@756b5b3
User@756b5b3
User@756b5b3
进程已结束,退出代码0
虽然他们的地址是一样的,但是HashSet仍不觉的这是同一对象
给 User
重写了 equals()
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
HashSet users = new HashSet<>();
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
users.add(new User("123123123"));
for(User u : users) System.out.println(u);
}
}
class User{
String number;
public User(String number) {
this.number = number;
}
@Override
public int hashCode() {
return Integer.parseInt(number);
}
@Override
public boolean equals(Object obj) {
return number.equals(((User)obj).number);
}
}
输出
User@756b5b3
进程已结束,退出代码0
成功对 User
去重
改进建议
重载构造函数类型冲突
//座机打手机 1
public CallRecord(String callingNumber,
String answerNumber, String answerAddressAreaCode,
Date startTime, Date endTime) {
super(callingNumber, answerNumber);
this.startTime = startTime;
this.endTime = endTime;
callingAddressAreaCode = callingNumber.substring(0, 4);
this.answerAddressAreaCode = answerAddressAreaCode;
}
//手机打座机 2
public CallRecord(String callingNumber, String callingAddressAreaCode,
String answerNumber,
Date startTime, Date endTime) {
super(callingNumber, answerNumber);
this.startTime = startTime;
this.endTime = endTime;
this.callingAddressAreaCode = callingAddressAreaCode;
}
解决方案1:
public CallRecord(String callingNumber,
String callingAreaCode_Or_AnsNumber,
String ansNumber_Or_AnsAreaCode,
Date startTime, Date endTime,
int mod) {
if (mod == 1) {
this.callingNumber = callingNumber;
this.answerNumber = callingAreaCode_Or_AnsNumber;
this.startTime = startTime;
this.endTime = endTime;
callingAddressAreaCode = callingNumber.substring(0, 4);
answerAddressAreaCode = ansNumber_Or_AnsAreaCode;
} else {
this.callingNumber = callingNumber;
this.answerNumber = ansNumber_Or_AnsAreaCode;
this.startTime = startTime;
this.endTime = endTime;
callingAddressAreaCode = callingAreaCode_Or_AnsNumber;
answerAddressAreaCode = ansNumber_Or_AnsAreaCode.substring(0, 4);
}
}
利用一个mod来判断使用哪个重载
解决方案2:
class CallRecord{
//*********************************************************************************//
public CallRecord(Number callingNumber, Number answerNumber, Date startTime, Date endTime) {
super(callingNumber, answerNumber);
this.startTime = startTime;
this.endTime = endTime;
}
//*********************************************************************************//
}
class Number{
String number,addressNumber;
public Number(String number, String addressNumber) {
this.number = number;
this.addressNumber = addressNumber;
}
}
用一个Number类来根治类型冲突的问题,思路也更清晰
总结
通过这几周的作业,克服了对正则表达式的恐惧,对程序的设计有了更开阔的思维,学会了用 java.text.SimpleDateFormat
格式化日期、用 java.util.Date
存储日期、还学会了用 HashSet<>
容器存储对象、以及用 Collections.sort()
对容器中实现 Compareable<>
接口的类的对象进行排序…..
Original: https://www.cnblogs.com/Pseach/p/16363430.html
Author: Pseach
Title: BLOG-3_JavaHomework_Summary
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/571526/
转载文章受原作者版权保护。转载请注明原作者出处!