第三次博客作业
一.前言
1.知识点总结
<1>电信系列的座机,电话,短信计费系列
考查的知识点为:
类设计的搭建与实现
SimpleDateFormat类实现输入,以及时间格式化处理
对不同通话记录的输入进行判断以及反应,通过正则表达式判断输入是否合法
类的封装、继承、多态、接口、抽象类的使用
集合框架,以及重写Collection的方法等
个人认为难点在于:
对不同种通话记录的添加以及详情计费方式
对于输入的通话记录,用正则表达式验证
非法输入情况的考虑,如用户是否出现重复,以及存在,如国内漫游接听也要收费
Collection里自己重写Comparator,学要了解源码,进行改进,改成需要的顺序
后期测试点太难过了
<2>PTA6—多态测试
要求模拟一个容器类层次结构,考察接口、重写抽象方法、和多态机制等知识点,在已有代码基础上增添,比较简单
<3>PTA7—删除集合元素—修改班级成员信息
对集合里元素的更改,主要考察它的遍历和删减重复元素,比较简单
<4>PTA7—添加元素到集合里—有序存储员工信息
考察集合包内的方法的使用
<5>PTA8—编写一个Shop(商店)、内部类InnerCoupons(内部购物券)
类的组合,继承,设计
<6>PTA8—设计一个动物发生模拟器
类的设计与方法实现
多态的使用
2.题量与难度评估
近三次作业题量适中,题目较之前的习题集难度减小,题目很巧妙,也很较符合实际生活
二.设计与分析
6_1.电信计费系列1-座机计费
实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
输入格式:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。
输出格式:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
建议类图:
参见图1、2、3,可根据理解自行调整:

图1 图1中User是用户类,包括属性: userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。 ChargeMode是计费方式的抽象类: chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。 getMonthlyRent()方法用于返回月租(monthlyRent)。 UserRecords是用户记录类,保存用户各种通话、短信的记录, 各种计费规则将使用其中的部分或者全部记录。 其属性从上到下依次是: 市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录 以及发送短信、接收短信的记录。

图2 图2中CommunicationRecord是抽象的通讯记录类: 包含callingNumber拨打号码、answerNumber接听号码两个属性。 CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。 CallRecord(通话记录类)包含属性: 通话的起始、结束时间以及 拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。 区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。

图3 图3是计费规则的相关类,这些类的核心方法是: calCost(ArrayList<CallRecord> callRecords)。 该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。 输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。 LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是 座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。 (提示:可以从UserRecords类中获取各种类型的callRecords)。

后续扩展说明:
后续题目集将增加手机用户,手机用户的计费方式中除了与座机计费类似的主叫通话费之外,还包含市外接听电话的漫游费以及发短信的费用。在本题的设计时可统一考虑。
通话记录中,手机需要额外记录拨打/接听的地点的区号,比如:
座机打手机:t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
短信的格式:m-主叫号码,接收号码,短信内容
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you
输入样例:
在这里给出一组输入。例如:
u-079186300001 0 t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25 end
输出样例:
在这里给出相应的输出。例如:
079186300001 3.0 77.0
代码:
1 import java.text.DecimalFormat; 2 import java.text.ParseException; 3 import java.text.SimpleDateFormat; 4 import java.util.*; 5 6 public class Main { 7 public static void main(String[] args) { 8 Scanner input = new Scanner(System.in); 9 ArrayList<Users> usersArrayList = new ArrayList<>(); 10 String str = input.nextLine(); 11 boolean repetition = false; 12 while (!str.equals("end")){ 13 if(str.matches("u\\-0791\\d{7,8}\\s0")){ 14 String str1[] = str.split("-"); 15 String str2[] = str1[1].split(" "); 16 for(int i = 0;i < usersArrayList.size();i++){ 17 if(usersArrayList.get(i).number.equals(str2[0])) { 18 repetition = true; 19 break; 20 } 21 } 22 if(repetition == false){ 23 usersArrayList.add(new Users(str2[0])); 24 } 25 } 26 if(str.matches("t-(\\d){11,12}\\s(\\d){10,12}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d")){ 27 String str3[] = str.split("-"); 28 String str4[] = str3[1].split(" "); 29 for (int i = 0;i < usersArrayList.size();i++){ 30 if(usersArrayList.get(i).number.equals(str4[0])){ 31 if(str4[1].substring(0,4).matches("0791")){ 32 usersArrayList.get(i).getUserRecords().addgetCallingInCityRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5])); 33 usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords()); 34 } 35 else if(str4[1].substring(0,4).matches("079\\d|0701")){ 36 usersArrayList.get(i).getUserRecords().addgetCallingInProvinceRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5])); 37 usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords()); 38 } 39 else 40 usersArrayList.get(i).getUserRecords().addgetCallingInLandRecords(new CallRecord(str4[2]+" "+str4[3],str4[4]+" "+str4[5])); 41 usersArrayList.get(i).setUserRecords(usersArrayList.get(i).getUserRecords()); 42 } 43 } 44 } 45 str = input.nextLine(); 46 } 47 48 Collections.sort(usersArrayList,new Comparator<Users>() { 49 @Override 50 public int compare(Users o1, Users o2) { 51 return o1.getNumber().compareTo(o2.getNumber()); 52 } 53 }); 54 for(int i = 0;i<usersArrayList.size();i++){ 55 System.out.print(usersArrayList.get(i).number+" "); 56 System.out.print(new DecimalFormat("0.0#").format(usersArrayList.get(i).calCost())+" "); 57 System.out.print(new DecimalFormat("0.0#").format(usersArrayList.get(i).getBalance()-usersArrayList.get(i).calCost()-20)); 58 System.out.println(); 59 } 60 } 61 } 62 63 class Users{ 64 private UserRecords userRecords = new UserRecords(); 65 double balance = 100; 66 String number; 67 ChargeMode chargeMode; 68 69 public Users(String number) { 70 this.number = number; 71 } 72 73 public double CalBalance(){ 74 return 0; 75 } 76 77 public double calCost(){ 78 LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule(); 79 LandPhoneInLandRule landPhoneInLandRule = new LandPhoneInLandRule(); 80 LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule(); 81 return landPhoneInLandRule.calCost(userRecords.getCallingInLandRecords())+landPhoneInCityRule.calCost(userRecords.getCallingInCityRecords())+landPhoneInProvinceRule.calCost(userRecords.getCallingInProvinceRecords()); 82 } 83 84 public UserRecords getUserRecords() { 85 return userRecords; 86 } 87 88 public void setUserRecords(UserRecords userRecords) { 89 this.userRecords = userRecords; 90 } 91 92 public double getBalance() { 93 return balance; 94 } 95 96 public String getNumber() { 97 return number; 98 } 99 100 public void setNumber(String number) { 101 this.number = number; 102 } 103 104 public ChargeMode getChargeMode() { 105 return chargeMode; 106 } 107 108 public void setChargeMode(ChargeMode chargeMode) { 109 this.chargeMode = chargeMode; 110 } 111 112 } 113 114 class UserRecords{ 115 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 116 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 117 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 118 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 119 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 120 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 121 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 122 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 123 124 public ArrayList<CallRecord> getCallingInCityRecords() { 125 return callingInCityRecords; 126 } 127 128 public ArrayList<CallRecord> getCallingInProvinceRecords() { 129 return callingInProvinceRecords; 130 } 131 132 public ArrayList<CallRecord> getCallingInLandRecords() { 133 return callingInLandRecords; 134 } 135 136 public ArrayList<CallRecord> getAnswerInCityRecords() { 137 return answerInCityRecords; 138 } 139 140 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 141 return answerInProvinceRecords; 142 } 143 144 public ArrayList<CallRecord> getAnswerInLandRecords() { 145 return answerInLandRecords; 146 } 147 148 public ArrayList<MessageRecord> getSendMessageRecords() { 149 return sendMessageRecords; 150 } 151 152 public ArrayList<MessageRecord> getReceiveMessageRecords() { 153 return receiveMessageRecords; 154 } 155 156 public void addgetCallingInCityRecords(CallRecord callRecord){ 157 getCallingInCityRecords().add(callRecord); 158 } 159 160 public void addgetCallingInProvinceRecords(CallRecord callRecord){ 161 getCallingInProvinceRecords().add(callRecord); 162 } 163 164 public void addgetCallingInLandRecords(CallRecord callRecord){ 165 getCallingInLandRecords().add(callRecord); 166 } 167 168 public void addAnswerInCityRecords(CallRecord answerRecord){ 169 answerInCityRecords.add(answerRecord); 170 } 171 172 public void addAnswerInProvinceRecords(CallRecord answerRecord){ 173 answerInProvinceRecords.add(answerRecord); 174 } 175 176 public void addAnswerInLandRecords(CallRecord answerRecord){ 177 answerInLandRecords.add(answerRecord); 178 } 179 180 public void addSendMessageRecords(MessageRecord sendMessageRecord){ 181 sendMessageRecords.add(sendMessageRecord); 182 } 183 184 public void addReceiveMessageRecords(MessageRecord receiveMessageRecord){ 185 receiveMessageRecords.add(receiveMessageRecord); 186 } 187 } 188 189 abstract class ChargeMode{ 190 private ArrayList<ChargeRule> chargeRules = new ArrayList<>(); 191 192 public ArrayList<ChargeRule> getChargeRules() { 193 return chargeRules; 194 } 195 196 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 197 this.chargeRules = chargeRules; 198 } 199 200 public double calCost(UserRecords userRecords){ 201 return 0; 202 } 203 204 public double getMonthlyRent(){ 205 206 return 20; 207 } 208 } 209 210 class LandlinePhoneCharging extends ChargeMode{ 211 private double monthlyRent = 20; 212 213 @Override 214 public double calCost(UserRecords userRecords) { 215 return 0; 216 } 217 218 @Override 219 public double getMonthlyRent() { 220 return monthlyRent; 221 } 222 } 223 224 abstract class CommunicationRecord{ 225 protected String callingNumber; 226 protected String answerNumber; 227 228 public String getCallingNumber() { 229 return callingNumber; 230 } 231 232 public void setCallingNumber(String callingNumber) { 233 234 this.callingNumber = callingNumber; 235 } 236 237 public String getAnswerNumber() { 238 return answerNumber; 239 } 240 241 public void setAnswerNumber(String answerNumber) { 242 this.answerNumber = answerNumber; 243 } 244 } 245 246 class CallRecord extends CommunicationRecord{ 247 private Date startTime; 248 private Date endTime; 249 private String callingAddressAreaCode; 250 private String answerAddressAreaCode; 251 252 public CallRecord(String startTime, String endTime) { 253 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); 254 try { 255 this.startTime = simpleDateFormat.parse(startTime); 256 } catch (ParseException e) { 257 e.printStackTrace(); 258 } 259 try { 260 this.endTime = simpleDateFormat.parse(endTime); 261 } catch (ParseException e) { 262 e.printStackTrace(); 263 } 264 } 265 266 public Date getStartTime() { 267 return startTime; 268 } 269 270 public void setStartTime(Date startTime) { 271 this.startTime = startTime; 272 } 273 274 public String getCallingAddressAreaCode() { 275 return callingAddressAreaCode; 276 } 277 278 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 279 this.callingAddressAreaCode = callingAddressAreaCode; 280 } 281 282 public Date getEndTime() { 283 return endTime; 284 } 285 286 public void setEndTime(Date endTime) { 287 this.endTime = endTime; 288 } 289 290 public String getAnswerAddressAreaCode() { 291 return answerAddressAreaCode; 292 } 293 294 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 295 this.answerAddressAreaCode = answerAddressAreaCode; 296 } 297 } 298 299 class MessageRecord extends CommunicationRecord{ 300 private String message; 301 302 public String getMessage() { 303 return message; 304 } 305 306 public void setMessage(String message) { 307 this.message = message; 308 } 309 } 310 311 abstract class ChargeRule{ 312 313 } 314 315 abstract class CallChargeRule extends ChargeRule{ 316 public double calCost(ArrayList<CallRecord> callRecords){ 317 318 return 0; 319 } 320 } 321 322 class LandPhoneInCityRule extends CallChargeRule{ 323 @Override 324 public double calCost(ArrayList<CallRecord> callRecords) { 325 double cost = 0; 326 double minutes; 327 for(CallRecord e:callRecords){ 328 long diff = e.getEndTime().getTime() - e.getStartTime().getTime(); 329 minutes = (int) Math.ceil((double) diff / (double) 60000); 330 cost += 0.1*minutes; 331 } 332 return cost; 333 } 334 } 335 336 class LandPhoneInLandRule extends CallChargeRule{ 337 @Override 338 public double calCost(ArrayList<CallRecord> callRecords) { 339 double cost = 0; 340 double minutes; 341 for(CallRecord e:callRecords){ 342 long diff = e.getEndTime().getTime() - e.getStartTime().getTime(); 343 minutes = (int) Math.ceil((double) diff / (double) 60000); 344 cost += 0.6*minutes; 345 } 346 return cost; 347 } 348 } 349 350 class LandPhoneInProvinceRule extends CallChargeRule{ 351 @Override 352 public double calCost(ArrayList<CallRecord> callRecords) { 353 double cost = 0; 354 double minutes; 355 for(CallRecord e:callRecords){ 356 long diff = e.getEndTime().getTime() - e.getStartTime().getTime(); 357 minutes = (int) Math.ceil((double) diff / (double) 60000); 358 cost += 0.3*minutes; 359 } 360 return cost; 361 } 362 }
分析:
对待非法输入时候时长没耐心琢磨,心静不下来导致的有些函数拼写错误及大小写搞混,由提交列表就可以看出本人代码急于求成,缺少实际经验的同时强调写作业效率,加上打字速度本来就慢,这导致函数常常出现拼写错误也多亏了编译器的报错,标红,让我一次次的修改,一次次的订正,一次次的反思,一次次的迭代,这告诫了我们要编程过程中要脚踏实地,宁愿降低自己的效率也要提高代码的可读性,降低代码的耦合性,让别人好找,自己好查代码存在的漏洞以及迭代的方法内容。
6_2.多态测试
定义容器Container接口。模拟实现一个容器类层次结构,并进行接口的实现、抽象方法重写和多态机制测试。各容器类实现求表面积、体积的方法。
定义接口Container:
属性:
public static final double pi=3.1415926;
抽象方法:
public abstract double area();
public abstract double volume();
static double sumofArea(Container c[]);
static double sumofVolume(Container c[]);
其中两个静态方法分别计算返回容器数组中所有对象的面积之和、周长之和;
定义Cube类、Cylinder类均实现自Container接口。
Cube类(属性:边长double类型)、Cylinder类(属性:底圆半径、高,double类型)。
输入格式:
第一行n表示对象个数,对象类型用cube、cylinder区分,cube表示立方体对象,后面输入边长,输入cylinder表示圆柱体对象,后面是底圆半径、高。
输出格式:
分别输出所有容器对象的表面积之和、体积之和,结果保留小数点后2位。
输入样例:
在这里给出一组输入。例如:
4 cube 15.7 cylinder 23.5 100 cube 46.8 cylinder 17.5 200
输出样例:
在这里给出相应的输出。例如:
56771.13 472290.12
代码:
1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args) { 4 /* 4 5 cube 6 15.7 7 cylinder 8 23.5 100 9 cube 10 46.8 11 cylinder 12 17.5 200*/ 13 Scanner input = new Scanner(System.in); 14 int n = input.nextInt(); 15 Shape3d[] arr = new Shape3d[n]; 16 for (int i = 0; i < arr.length; i++) { 17 String str = input.next(); 18 if(str.equals("cube")){ 19 arr[i] = new Cube(input.nextDouble()); 20 }else if(str.equals("cylinder")){ 21 arr[i] = new Cylinder(input.nextDouble(),input.nextDouble()); 22 } 23 } 24 double sum1 = 0;//总表面积初始化 25 double sum2 = 0;//总体积初始化 26 for (Shape3d i:arr) { 27 sum1 += i.area(); 28 sum2 += i.volume(); 29 } 30 double sumS = (double) Math.round(sum1 * 100) / 100; 31 double sumV = (double) Math.round(sum2* 100) / 100; 32 System.out.println(sumS); 33 System.out.println(sumV); 34 35 } 36 } 37 38 interface Container { 39 //属性 40 public static final double pi=3.1415926; 41 //方法 42 public abstract double area();//求表面积 43 public abstract double volume();//求体积 44 45 static double sumofArea(Container c[]) { 46 double sum = 0; 47 for (Container i:c) { 48 sum += i.area(); 49 } 50 return sum; 51 } 52 53 static double sumofVolume(Container c[]) { 54 double sum = 0; 55 for (Container i:c) { 56 sum += i.volume(); 57 } 58 return sum; 59 } 60 } 61 62 abstract class Shape3d implements Container{ 63 @Override 64 public abstract double area();//求立体图形表面积 65 66 67 68 @Override 69 public abstract double volume();//求立体图形体积 70 } 71 72 class Cube extends Shape3d{//立方体,也就是正方体 73 //属性:正方体的边长 74 private double a; 75 76 public Cube() { 77 } 78 79 public Cube(double a) { 80 this.a = a; 81 } 82 83 public double getA() { 84 return a; 85 } 86 87 public void setA(double a) { 88 this.a = a; 89 } 90 91 @Override 92 public double area() {//正方体表面积 93 return 6*a*a; 94 } 95 96 @Override 97 public double volume() {//正方体体积 98 return a*a*a; 99 } 100 } 101 102 103 class Cylinder extends Shape3d{//圆柱体 104 //半径和高 105 private double r,h; 106 107 public Cylinder() { 108 } 109 110 public Cylinder(double r, double h) { 111 this.r = r; 112 this.h = h; 113 } 114 115 public double getR() { 116 return r; 117 } 118 119 public void setR(double r) { 120 this.r = r; 121 } 122 123 public double getH() { 124 return h; 125 } 126 127 public void setH(double h) { 128 this.h = h; 129 } 130 131 @Override 132 public double area() {//表面积,两个圆面积加一个侧面面积 133 return 2*pi*r*r + 2*pi*r*h; 134 } 135 136 @Override 137 public double volume() {//体积,圆面积乘高 138 return pi*r*r*h; 139 } 140 141 }
分析:
这题主要是对继承,多态,接口等知识的掌握,懂相关的知识并且按照题目的要求去写还是比较简单的。
7_1.电信计费系列2-手机+座机计费
实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
1、针对市内座机用户采用的计费方式(与电信计费系列1内容相同):
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
假设本市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
2、针对手机用户采用实时计费方式:
月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟;
注:被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
输入:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,含手机和座机用户
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题在电信计费系列1基础上增加类型1-手机实时计费。
手机设置0或者座机设置成1,此种错误可不做判断。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
输入格式增加手机接打电话以及收发短信的格式,手机接打电话的信息除了号码之外需要额外记录拨打/接听的地点的区号,比如:
座机打手机:
t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:
t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
建议类图:
参见图1、2、3:

图1
图1中User是用户类,包括属性: userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。 ChargeMode是计费方式的抽象类: chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。 getMonthlyRent()方法用于返回月租(monthlyRent)。 UserRecords是用户记录类,保存用户各种通话、短信的记录, 各种计费规则将使用其中的部分或者全部记录。 其属性从上到下依次是: 市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录 以及发送短信、接收短信的记录。

图2
图2中CommunicationRecord是抽象的通讯记录类: 包含callingNumber拨打号码、answerNumber接听号码两个属性。 CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。CallRecord(通话记录类)包含属性: 通话的起始、结束时间以及 拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。 区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。

图3
图3是计费规则的相关类,这些类的核心方法是: calCost(ArrayList<CallRecord> callRecords)。 该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。 输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。 SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。 LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
输入样例:
在这里给出一组输入。例如:
u-13811111111 1 t-13811111111 0791 13811111110 020 2022.1.3 08:00:00 2022.1.3 08:09:20 end
输出样例:
在这里给出相应的输出。例如:
13811111111 3.0 82.0
代码:
1 import java.util.ArrayList; 2 import java.util.Comparator; 3 import java.util.Scanner; 4 import java.util.regex.Matcher; 5 import java.util.regex.Pattern; 6 import java.math.BigDecimal; 7 import java.text.SimpleDateFormat; 8 import java.util.Date; 9 import java.util.Locale; 10 import java.text.ParseException; 11 12 public class Main { 13 14 public static void main(String[] args) { 15 16 Outputtool outputtool = new Outputtool(); 17 18 Inputdeal inputdeal = new Inputdeal(); 19 20 ArrayList<User> users = new ArrayList<>(); 21 22 Scanner in = new Scanner(System.in); 23 24 String input = in.nextLine(); 25 26 while (!input.equals("end")) { 27 if (1 == inputdeal.check(input)) { 28 inputdeal.writeUser(users, input); 29 } else if (2 == inputdeal.check(input)) { 30 inputdeal.writeRecord(users, input); 31 } 32 input = in.nextLine(); 33 } 34 35 users.sort(new Comparator<User>() { 36 37 @Override 38 public int compare(User u1, User u2) { 39 if (u1.getNumber().charAt(0) == '0' && u2.getNumber().charAt(0) != '0') { 40 return -1; 41 } else if (u1.getNumber().charAt(0) != '0' && u2.getNumber().charAt(0) == '0') { 42 return 1; 43 } 44 if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) { 45 return 1; 46 } else { 47 return -1; 48 } 49 } 50 }); 51 52 for (User u : users) { 53 System.out.print(u.getNumber() + " "); 54 outputtool.output(u.calCost()); 55 System.out.print(" "); 56 outputtool.output(u.calBalance()); 57 System.out.println(); 58 59 } 60 61 } 62 63 } 64 65 abstract class ChargeMode { 66 protected ArrayList<ChargeRule> chargeRules = new ArrayList<>(); 67 68 public abstract double calCost(UserRecords userRecords); 69 70 public abstract double getMonthlyRent(); 71 72 public ArrayList<ChargeRule> getChargeRules() { 73 return chargeRules; 74 } 75 76 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 77 this.chargeRules = chargeRules; 78 } 79 } 80 81 class UserRecords { 82 83 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 84 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 85 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 86 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 87 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 88 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 89 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 90 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 91 92 public void addCallingInCityRecords(CallRecord callRecord) { 93 callingInCityRecords.add(callRecord); 94 } 95 96 public void addCallingInProvinceRecords(CallRecord callRecord) { 97 callingInProvinceRecords.add(callRecord); 98 } 99 100 public void addCallingInLandRecords(CallRecord callRecord) { 101 callingInLandRecords.add(callRecord); 102 } 103 104 public void addAnswerInCityRecords(CallRecord callRecord) { 105 answerInCityRecords.add(callRecord); 106 } 107 108 public void aaddAnswerInProvinceRecords(CallRecord callRecord) { 109 answerInProvinceRecords.add(callRecord); 110 } 111 112 public void addAnswerInLandRecords(CallRecord callRecord) { 113 answerInLandRecords.add(callRecord); 114 } 115 116 public void addSendMessageRecords(MessageRecord callRecord) { 117 sendMessageRecords.add(callRecord); 118 } 119 120 public void addReceiveMessageRecords(MessageRecord callRecord) { 121 receiveMessageRecords.add(callRecord); 122 } 123 124 public ArrayList<CallRecord> getCallingInCityRecords() { 125 return callingInCityRecords; 126 } 127 128 public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) { 129 this.callingInCityRecords = callingInCityRecords; 130 } 131 132 public ArrayList<CallRecord> getCallingInProvinceRecords() { 133 return callingInProvinceRecords; 134 } 135 136 public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) { 137 this.callingInProvinceRecords = callingInProvinceRecords; 138 } 139 140 public ArrayList<CallRecord> getCallingInLandRecords() { 141 return callingInLandRecords; 142 } 143 144 public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) { 145 this.callingInLandRecords = callingInLandRecords; 146 } 147 148 public ArrayList<CallRecord> getAnswerInCityRecords() { 149 return answerInCityRecords; 150 } 151 152 public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) { 153 this.answerInCityRecords = answerInCityRecords; 154 } 155 156 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 157 return answerInProvinceRecords; 158 } 159 160 public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) { 161 this.answerInProvinceRecords = answerInProvinceRecords; 162 } 163 164 public ArrayList<CallRecord> getAnswerInLandRecords() { 165 return answerInLandRecords; 166 } 167 168 public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) { 169 this.answerInLandRecords = answerInLandRecords; 170 } 171 172 public ArrayList<MessageRecord> getSendMessageRecords() { 173 return sendMessageRecords; 174 } 175 176 public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) { 177 this.sendMessageRecords = sendMessageRecords; 178 } 179 180 public ArrayList<MessageRecord> getReceiveMessageRecords() { 181 return receiveMessageRecords; 182 } 183 184 public void setReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) { 185 this.receiveMessageRecords = receiveMessageRecords; 186 } 187 188 } 189 190 class LandlinePhoneCharging extends ChargeMode { 191 192 private double monthlyRent = 20; 193 194 public LandlinePhoneCharging() { 195 super(); 196 chargeRules.add(new LandPhoneInCityRule()); 197 chargeRules.add(new LandPhoneInProvinceRule()); 198 chargeRules.add(new LandPhoneInlandRule()); 199 } 200 201 @Override 202 public double calCost(UserRecords userRecords) { 203 double sumCost = 0; 204 for (ChargeRule rule : chargeRules) { 205 sumCost += rule.calCost(userRecords); 206 } 207 return sumCost; 208 } 209 210 @Override 211 public double getMonthlyRent() { 212 return monthlyRent; 213 } 214 215 } 216 217 class MobilePhoneCharging extends ChargeMode { 218 219 private double monthlyRent = 15; 220 221 public MobilePhoneCharging() { 222 super(); 223 chargeRules.add(new MobilePhoneInCityRule()); 224 chargeRules.add(new MobilePhoneInProvinceRule()); 225 chargeRules.add(new MobilePhoneInlandRule()); 226 } 227 228 @Override 229 public double calCost(UserRecords userRecords) { 230 double sumCost = 0; 231 for (ChargeRule rule : chargeRules) { 232 sumCost += rule.calCost(userRecords); 233 } 234 return sumCost; 235 } 236 237 @Override 238 public double getMonthlyRent() { 239 return monthlyRent; 240 } 241 242 } 243 244 class Inputdeal { 245 246 public int check(String input) { 247 if (input.matches("[u]-0791[0-9]{7,8}\\s[0]") || input.matches("[u]-1[0-9]{10}\\s[1]")) { 248 return 1; 249 // } else if (input.charAt(0) == 'm') { 250 // return 2; 251 } else if (input.matches("(([t]-0791[0-9]{7,8}\\s" + "0[0-9]{9,11}\\s)|" 252 + "([t]-0791[0-9]{7,8}\\s" + "1[0-9]{10}\\s" + "0[0-9]{2,3}\\s)|" 253 + "([t]-1[0-9]{10}\\s" + "0[0-9]{2,3}\\s" + "0[0-9]{9,11}\\s)|" 254 + "([t]-1[0-9]{10}\\s" + "0[0-9]{2,3}\\s" + "1[0-9]{10}\\s" + "0[0-9]{2,3}\\s))" 255 256 + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(0?" 257 + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" 258 + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" 259 + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\\s" 260 + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.((([13578]|1[02])\\.(" 261 + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" 262 + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" 263 + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])")) { 264 return 2; 265 } 266 return 0; 267 } 268 269 @SuppressWarnings("unused") 270 private boolean validatet(String string) { 271 if (!string.matches("^([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$")) { 272 return false; 273 } 274 return true; 275 } 276 277 public static boolean validate(String dateString) { 278 // 使用正则表达式 测试 字符 符合 dddd.dd.dd 的格式(d表示数字) 279 Pattern p = Pattern.compile("\\d{4}+[\\.]\\d{1,2}+[\\.]\\d{1,2}+"); 280 Matcher m = p.matcher(dateString); 281 if (!m.matches()) { 282 return false; 283 } 284 285 // 得到年月日 286 String[] array = dateString.split("\\."); 287 int year = Integer.valueOf(array[0]); 288 int month = Integer.valueOf(array[1]); 289 int day = Integer.valueOf(array[2]); 290 291 if (month < 1 || month > 12) { 292 return false; 293 } 294 int[] monthLengths = new int[] { 0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 295 if (isLeapYear(year)) { 296 monthLengths[2] = 29; 297 } else { 298 monthLengths[2] = 28; 299 } 300 int monthLength = monthLengths[month]; 301 if (day < 1 || day > monthLength) { 302 return false; 303 } 304 return true; 305 } 306 307 /** 是否是闰年 */ 308 private static boolean isLeapYear(int year) { 309 return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); 310 } 311 312 public boolean judge(String input) { 313 314 return false; 315 } 316 317 public void writeUser(ArrayList<User> users, String input) { 318 User usernew = new User(); 319 String[] inputs = input.split(" "); 320 String num = inputs[0].substring(2); 321 for (User i : users) { 322 if (i.getNumber().equals(num)) { 323 return; 324 } 325 } 326 usernew.setNumber(num); 327 int mode = Integer.parseInt(inputs[1]); 328 if (mode == 0) { 329 usernew.setChargeMode(new LandlinePhoneCharging()); 330 } else if (mode == 1) { 331 usernew.setChargeMode(new MobilePhoneCharging()); 332 } 333 users.add(usernew); 334 } 335 336 public void writeRecord(ArrayList<User> users, String input) { 337 String[] inputs = input.split(" "); 338 339 User callu = null, answeru = null; 340 CallRecord callrecord = new CallRecord(inputs); 341 342 if (input.charAt(0) == 't') { 343 String out = inputs[0]; 344 String in = ""; 345 if (inputs.length == 6) { 346 in = inputs[1]; 347 } else if (inputs.length == 7) { 348 in = inputs[1]; 349 } else if (inputs.length == 8) { 350 in = inputs[2]; 351 } 352 353 for (User i : users) { 354 if (i.getNumber().equals(out)) { 355 callu = i; 356 } 357 if (i.getNumber().equals(in)) { 358 answeru = i; 359 } 360 if (callu != null && answeru != null) { 361 break; 362 } 363 } 364 365 if (callu != null) { 366 if (callrecord.getCallType().matches("^1[1-3]$")) { 367 callu.getUserRecords().addCallingInCityRecords(callrecord); 368 } else if (callrecord.getCallType().matches("^2[1-3]$")) { 369 callu.getUserRecords().addCallingInProvinceRecords(callrecord); 370 } else { 371 callu.getUserRecords().addCallingInLandRecords(callrecord); 372 } 373 } 374 375 if (answeru != null) { 376 if (callrecord.getCallType().matches("^[1-3]1$")) { 377 answeru.getUserRecords().addAnswerInCityRecords(callrecord); 378 } else if (callrecord.getCallType().matches("^[1-3]2$")) { 379 answeru.getUserRecords().aaddAnswerInProvinceRecords(callrecord); 380 } else { 381 answeru.getUserRecords().addAnswerInLandRecords(callrecord); 382 } 383 } 384 } else if (input.charAt(0) == 'm') { 385 386 } 387 388 } 389 390 } 391 392 abstract class CommunicationRecord { 393 protected String callingNumber; 394 protected String answerNumbe; 395 396 public String getCallingNumber() { 397 return callingNumber; 398 } 399 400 public void setCallingNumber(String callingNumber) { 401 this.callingNumber = callingNumber; 402 } 403 404 public String getAnswerNumbe() { 405 return answerNumbe; 406 } 407 408 public void setAnswerNumbe(String answerNumbe) { 409 this.answerNumbe = answerNumbe; 410 } 411 412 } 413 414 abstract class ChargeRule { 415 416 abstract public double calCost(UserRecords userRecords); 417 418 } 419 420 class CallRecord extends CommunicationRecord { 421 private Date startTime; 422 private Date endTime; 423 private String callingAddressAreaCode; 424 private String answerAddressAreaCode; 425 426 public String getCallType() { 427 String type = ""; 428 if (callingAddressAreaCode.equals("0791")) { 429 type = type.concat("1"); 430 } else if (callingAddressAreaCode.matches("^079[023456789]$") || callingAddressAreaCode.equals("0701")) { 431 type = type.concat("2"); 432 } else { 433 type = type.concat("3"); 434 } 435 436 if (answerAddressAreaCode.equals("0791")) { 437 type = type.concat("1"); 438 } else if (answerAddressAreaCode.matches("^079[023456789]$") || answerAddressAreaCode.equals("0701")) { 439 type = type.concat("2"); 440 } else { 441 type = type.concat("3"); 442 } 443 444 return type; 445 } 446 447 public CallRecord(String[] inputs) { 448 super(); 449 450 char type = inputs[0].charAt(0); 451 inputs[0] = inputs[0].substring(2); 452 453 String sd = null, st = null, ed = null, et = null; 454 455 if (type == 't') { 456 if (inputs.length == 6) { 457 sd = inputs[2]; 458 st = inputs[3]; 459 ed = inputs[4]; 460 et = inputs[5]; 461 callingAddressAreaCode = inputs[0].substring(0, 4); 462 answerAddressAreaCode = inputs[1].substring(0, 4); 463 } else if (inputs.length == 7) { 464 sd = inputs[3]; 465 st = inputs[4]; 466 ed = inputs[5]; 467 et = inputs[6]; 468 if (inputs[0].charAt(0) != '0') { 469 if (inputs[2].length() == 10) { 470 answerAddressAreaCode = inputs[2].substring(0, 3); 471 } else { 472 answerAddressAreaCode = inputs[2].substring(0, 4); 473 } 474 callingAddressAreaCode = inputs[1]; 475 } else { 476 if (inputs[0].length() == 10) { 477 callingAddressAreaCode = inputs[0].substring(0, 3); 478 } else { 479 callingAddressAreaCode = inputs[0].substring(0, 4); 480 } 481 answerAddressAreaCode = inputs[2]; 482 } 483 } else if (inputs.length == 8) { 484 sd = inputs[4]; 485 st = inputs[5]; 486 ed = inputs[6]; 487 et = inputs[7]; 488 callingAddressAreaCode = inputs[1]; 489 answerAddressAreaCode = inputs[3]; 490 } 491 } else if (type == 'm') { 492 493 } 494 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault()); 495 try { 496 startTime = simpleDateFormat.parse(sd + " " + st); 497 endTime = simpleDateFormat.parse(ed + " " + et); 498 } catch (ParseException e) { 499 } 500 501 } 502 503 public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) { 504 super(); 505 this.startTime = startTime; 506 this.endTime = endTime; 507 this.callingAddressAreaCode = callingAddressAreaCode; 508 this.answerAddressAreaCode = answerAddressAreaCode; 509 } 510 511 public Date getStartTime() { 512 return startTime; 513 } 514 515 public void setStartTime(Date startTime) { 516 this.startTime = startTime; 517 } 518 519 public Date getEndTime() { 520 return endTime; 521 } 522 523 public void setEndTime(Date endTime) { 524 this.endTime = endTime; 525 } 526 527 public String getCallingAddressAreaCode() { 528 return callingAddressAreaCode; 529 } 530 531 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 532 this.callingAddressAreaCode = callingAddressAreaCode; 533 } 534 535 public String getAnswerAddressAreaCode() { 536 return answerAddressAreaCode; 537 } 538 539 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 540 this.answerAddressAreaCode = answerAddressAreaCode; 541 } 542 } 543 544 abstract class CallChargeRule extends ChargeRule { 545 546 } 547 548 class LandPhoneInCityRule extends CallChargeRule { 549 550 @Override 551 public double calCost(UserRecords userRecords) { 552 double sumCost = 0; 553 for (CallRecord call : userRecords.getCallingInCityRecords()) { 554 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 555 if (distanceS < 0) { 556 continue; 557 } 558 double distanceM = (int) distanceS / 60; 559 if (distanceS % 60 != 0) { 560 distanceM += 1; 561 } 562 if (call.getCallType().equals("11")) { 563 sumCost += distanceM * 0.1; 564 } else if (call.getCallType().equals("12")) { 565 sumCost += distanceM * 0.3; 566 } else if (call.getCallType().equals("13")) { 567 sumCost += distanceM * 0.6; 568 } 569 } 570 return sumCost; 571 } 572 573 } 574 575 class LandPhoneInlandRule extends CallChargeRule { 576 577 @Override 578 public double calCost(UserRecords userRecords) { 579 double sumCost = 0; 580 for (CallRecord call : userRecords.getCallingInLandRecords()) { 581 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 582 if (distanceS < 0) { 583 continue; 584 } 585 double distanceM = (int) distanceS / 60; 586 if (distanceS % 60 != 0) { 587 distanceM += 1; 588 } 589 sumCost += distanceM * 0.6; 590 } 591 return sumCost; 592 } 593 594 } 595 596 class LandPhoneInProvinceRule extends CallChargeRule { 597 598 @Override 599 public double calCost(UserRecords userRecords) { 600 double sumCost = 0; 601 for (CallRecord call : userRecords.getCallingInProvinceRecords()) { 602 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 603 if (distanceS < 0) { 604 continue; 605 } 606 double distanceM = (int) distanceS / 60; 607 if (distanceS % 60 != 0) { 608 distanceM += 1; 609 } 610 sumCost += distanceM * 0.3; 611 } 612 return sumCost; 613 } 614 615 } 616 617 class MobilePhoneInCityRule extends CallChargeRule { 618 619 @Override 620 public double calCost(UserRecords userRecords) { 621 double sumCost = 0; 622 for (CallRecord call : userRecords.getCallingInCityRecords()) { 623 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 624 if (distanceS < 0) { 625 continue; 626 } 627 double distanceM = (int) distanceS / 60; 628 if (distanceS % 60 != 0) { 629 distanceM += 1; 630 } 631 if (call.getCallType().equals("11")) { 632 sumCost += distanceM * 0.1; 633 } else if (call.getCallType().equals("12")) { 634 sumCost += distanceM * 0.2; 635 } else if (call.getCallType().equals("13")) { 636 sumCost += distanceM * 0.3; 637 } 638 639 } 640 return sumCost; 641 } 642 643 } 644 645 class MobilePhoneInlandRule extends CallChargeRule { 646 647 @Override 648 public double calCost(UserRecords userRecords) { 649 double sumCost = 0; 650 for (CallRecord call : userRecords.getCallingInLandRecords()) { 651 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 652 if (distanceS < 0) { 653 continue; 654 } 655 double distanceM = (int) distanceS / 60; 656 if (distanceS % 60 != 0) { 657 distanceM += 1; 658 } 659 sumCost += distanceM * 0.6; 660 } 661 for (CallRecord call : userRecords.getAnswerInLandRecords()) { 662 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 663 if (distanceS < 0) { 664 continue; 665 } 666 double distanceM = (int) distanceS / 60; 667 if (distanceS % 60 != 0) { 668 distanceM += 1; 669 } 670 sumCost += distanceM * 0.3; 671 } 672 return sumCost; 673 } 674 675 } 676 677 class MobilePhoneInProvinceRule extends CallChargeRule { 678 679 @Override 680 public double calCost(UserRecords userRecords) { 681 double sumCost = 0; 682 for (CallRecord call : userRecords.getCallingInProvinceRecords()) { 683 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 684 if (distanceS < 0) { 685 continue; 686 } 687 double distanceM = (int) distanceS / 60; 688 if (distanceS % 60 != 0) { 689 distanceM += 1; 690 } 691 if (call.getCallType().equals("21")) { 692 sumCost += distanceM * 0.3; 693 } else if (call.getCallType().equals("22")) { 694 sumCost += distanceM * 0.3; 695 } else if (call.getCallType().equals("23")) { 696 sumCost += distanceM * 0.3; 697 } 698 } 699 return sumCost; 700 } 701 702 } 703 704 class MessageRecord extends CommunicationRecord { 705 706 private String message; 707 708 public String getMessage() { 709 return message; 710 } 711 712 public void setMessage(String message) { 713 this.message = message; 714 } 715 } 716 717 class User { 718 719 private UserRecords userRecords = new UserRecords(); 720 private double balance = 100; 721 private ChargeMode chargeMode; 722 private String number; 723 724 public double calCost() { 725 return chargeMode.calCost(userRecords); 726 } 727 728 public double calBalance() { 729 return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords); 730 } 731 732 public UserRecords getUserRecords() { 733 return userRecords; 734 } 735 736 public void setUserRecords(UserRecords userRecords) { 737 this.userRecords = userRecords; 738 } 739 740 public ChargeMode getChargeMode() { 741 return chargeMode; 742 } 743 744 public void setChargeMode(ChargeMode chargeMode) { 745 this.chargeMode = chargeMode; 746 } 747 748 public String getNumber() { 749 return number; 750 } 751 752 public void setNumber(String number) { 753 this.number = number; 754 } 755 756 } 757 758 class Outputtool { 759 760 @SuppressWarnings("deprecation") 761 public void output(double out) { 762 // java.text.DecimalFormat df=new java.text.DecimalFormat("#.##"); 763 // String a=df.format(out); 764 // System.out.print(a); 765 BigDecimal numb = new BigDecimal(out); 766 out = numb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); 767 System.out.print(out); 768 } 769 }
7_2.sdut-Collection-sort--C~K的班级(II)
经过不懈的努力,C~K终于当上了班主任。
现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个,
但是工作量太大了,所以找到了会编程的你,你能帮他解决这个问题吗?
输入格式:
第一行输入一个N,代表C~K导出的名单共有N行(N<100000).
接下来的N行,每一行包括一个同学的信息,学号 姓名 年龄 性别。
输出格式:
第一行输出一个n,代表删除重复名字后C~K的班级共有几人。
接下来的n行,输出每一个同学的信息,输出按照学号从小到大的顺序。
输入样例:
6 0001 MeiK 20 M 0001 MeiK 20 M 0002 sdk2 21 M 0002 sdk2 21 M 0002 sdk2 21 M 0000 blf2 22 F
输出样例:
3 0000 blf2 22 F 0001 MeiK 20 M 0002 sdk2 21 M
代码:
1 import java.util.*; 2 public class Main { 3 public static void main(String[] args){ 4 HashSet<Student> students = new HashSet<>(); 5 Scanner input = new Scanner(System.in); 6 int N = input.nextInt();//班级人数 7 for(int i=0;i<N;i++){ 8 students.add(new Student(input.next(),input.next(),input.nextInt(),input.next())) ; 9 } 10 System.out.println(students.size()); 11 ArrayList<Student> studentArrayList = new ArrayList<>(students); 12 Collections.sort(studentArrayList); 13 for (Student student : studentArrayList) System.out.println(student.sno + " " + student.name + " " + student.age + " " + student.gender); 14 } 15 } 16 class Student implements Comparable<Student>{ 17 String sno;//学号 18 String name;//姓名 19 int age;//年龄 20 String gender;//性别 21 public Student(String sno,String name,int age,String gender){ 22 this.sno = sno; 23 this.name = name; 24 this.age = age; 25 this.gender = gender; 26 } 27 public boolean equals(Object obj) { 28 return sno.equals(((Student) obj).sno); 29 } 30 31 public String toString() { 32 return sno + " " + name + " " + age + " " + sno; 33 } 34 @Override 35 public int compareTo(Student o) { 36 return Integer.compare(Integer.parseInt(sno), Integer.parseInt(o.sno)); 37 } 38 public int hashCode() { 39 return Integer.parseInt(sno); 40 } 41 }
分析:
这里运用了拉姆达表达式解决该问题,保持了学号对应的姓名,年龄,性别的连接性是一个不错的解决方法,在复习拉姆达表达式的同时,也让我们体会到了拉姆达表达式的实用性,是一个非常不错的题目。
7_3.阅读程序,按照题目需求修改程序
功能需求:
使用集合存储3个员工的信息(有序);
通过迭代器依次找出所有的员工。
提示:学生复制以下代码到编程区,并按需求进行调试修改。
// 1、导入相关包
//定义员工类
class Employee {
private String name;
private int age;
public Employee() {
super();
}
public Employee(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 class Main {
public static void main(String[] args) {
// 1、创建有序集合对象
Collection c ;
// 创建3个员工元素对象
for (int i = 0; i < 3; i++) {
Scanner sc = new Scanner(System.in);
String employeeName = sc.nextLine();
int employeeAge = sc.nextInt();
Employee employee = new Employee(employeeName, employeeAge);
c.add(employee);
}
// 2、创建迭代器遍历集合
Iterator it;
//3、遍历
while (it.hasnext) {
//4、集合中对象未知,向下转型
Employee e = it.next();
System.out.println(e.getName() + "---" + e.getAge());
}
}
}
输入样例:
在这里给出一组输入。例如:
zs 10 ls 20 ww 30
输出样例:
在这里给出相应的输出。例如
zs---10 ls---20 ww---30
代码:
1 // 1、导入相关包 2 import java.util.*; 3 //定义员工类 4 class Employee { 5 6 private String name; 7 private int age; 8 9 public Employee() { 10 super(); 11 } 12 13 public Employee(String name, int age) { 14 super(); 15 this.name = name; 16 this.age = age; 17 } 18 19 public String getName() { 20 return name; 21 } 22 23 public void setName(String name) { 24 this.name = name; 25 } 26 27 public int getAge() { 28 return age; 29 } 30 31 public void setAge(int age) { 32 this.age = age; 33 } 34 } 35 36 //主函数 37 public class Main { 38 39 public static void main(String[] args) { 40 // 1、创建有序集合对象 41 Collection<Employee> c = new ArrayList<>(); 42 43 // 创建3个员工元素对象 44 for (int i = 0; i < 3; i++) { 45 Scanner sc = new Scanner(System.in); 46 String employeeName = sc.nextLine(); 47 int employeeAge = sc.nextInt(); 48 49 Employee employee = new Employee(employeeName, employeeAge); 50 c.add(employee); 51 } 52 53 54 55 // 2、创建迭代器遍历集合 56 Iterator<Employee> it = c.iterator(); 57 58 //3、遍历 59 while (it.hasNext()) { 60 61 //4、集合中对象未知,向下转型 62 Employee e = it.next(); 63 64 System.out.println(e.getName() + "---" + e.getAge()); 65 } 66 } 67 68 }
分析:
这题就是对给定的代码进行编译测试,调试运行,这里面只需要改 创建有序集合对象 和 创建迭代器遍历集合 这两部分,第一个是缺少创建集合对象,第二个是没有使用迭代器。
8_1.电信计费系列3-短信计费
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
输入:
输入信息包括两种类型
1、逐行输入南昌市手机用户开户的信息,每行一个用户。
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐 3-手机短信计费)
例如:u-13305862264 3
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题只针对类型3-手机短信计费。
2、逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.
注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
本题只考虑短信计费,不考虑通信费用以及月租费。
建议类图:
参见图1、2、3:

图1
图1中User是用户类,包括属性: userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。 ChargeMode是计费方式的抽象类: chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。 getMonthlyRent()方法用于返回月租(monthlyRent)。 UserRecords是用户记录类,保存用户各种通话、短信的记录, 各种计费规则将使用其中的部分或者全部记录。 其属性从上到下依次是: 市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录 以及发送短信、接收短信的记录。

图2
图2中CommunicationRecord是抽象的通讯记录类: 包含callingNumber拨打号码、answerNumber接听号码两个属性。 CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。

图3
图3是计费规则的相关类,这些类的核心方法是: calCost(ArrayList callRecords)。 该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。 输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。 SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。 LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。 (提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
输入样例:
在这里给出一组输入。例如:
u-18907910010 3 m-18907910010 13305862264 aaaaaaaaaaaaaaaaaaaaaaa end
输出样例:
在这里给出相应的输出。例如:
18907910010 0.3 99.7
### 输入样例1:
在这里给出一组输入。例如:
u-18907910010 3 m-18907910010 13305862264 aaaaaaaaaaaa m-18907910010 13305862264 aaaaaaa. m-18907910010 13305862264 bb,bbbb end
输出样例1:
在这里给出相应的输出。例如:
18907910010 0.5 99.5
代码:
1 2 3 import java.util.ArrayList; 4 import java.util.Comparator; 5 import java.util.Scanner; 6 import java.util.regex.Matcher; 7 import java.util.regex.Pattern; 8 import java.math.BigDecimal; 9 import java.text.SimpleDateFormat; 10 import java.util.Date; 11 import java.util.Locale; 12 import java.text.ParseException; 13 14 public class Main { 15 16 public static void main(String[] args) { 17 18 Outputtool outputtool = new Outputtool(); 19 20 Inputdeal inputdeal = new Inputdeal(); 21 22 ArrayList<User> users = new ArrayList<>(); 23 24 Scanner in = new Scanner(System.in); 25 26 String input = in.nextLine(); 27 28 while (!input.equals("end")) { 29 if (1 == inputdeal.check(input)) { 30 inputdeal.writeUser(users, input); 31 } else if (2 == inputdeal.check(input)) { 32 inputdeal.writeRecord(users, input); 33 } 34 input = in.nextLine(); 35 } 36 37 users.sort(new Comparator<User>() { 38 39 @Override 40 public int compare(User u1, User u2) { 41 if (u1.getNumber().charAt(0) == '0' && u2.getNumber().charAt(0) != '0') { 42 return -1; 43 } else if (u1.getNumber().charAt(0) != '0' && u2.getNumber().charAt(0) == '0') { 44 return 1; 45 } 46 if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) { 47 return 1; 48 } else { 49 return -1; 50 } 51 } 52 }); 53 54 for (User u : users) { 55 System.out.print(u.getNumber() + " "); 56 outputtool.output(u.calCost()); 57 System.out.print(" "); 58 outputtool.output(u.calBalance()); 59 System.out.println(); 60 61 } 62 63 } 64 65 } 66 67 abstract class ChargeMode { 68 protected ArrayList<ChargeRule> chargeRules = new ArrayList<>(); 69 70 public abstract double calCost(UserRecords userRecords); 71 72 public abstract double getMonthlyRent(); 73 74 public ArrayList<ChargeRule> getChargeRules() { 75 return chargeRules; 76 } 77 78 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 79 this.chargeRules = chargeRules; 80 } 81 } 82 83 class UserRecords { 84 85 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 86 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 87 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 88 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 89 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 90 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 91 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 92 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 93 94 public void addCallingInCityRecords(CallRecord callRecord) { 95 callingInCityRecords.add(callRecord); 96 } 97 98 public void addCallingInProvinceRecords(CallRecord callRecord) { 99 callingInProvinceRecords.add(callRecord); 100 } 101 102 public void addCallingInLandRecords(CallRecord callRecord) { 103 callingInLandRecords.add(callRecord); 104 } 105 106 public void addAnswerInCityRecords(CallRecord callRecord) { 107 answerInCityRecords.add(callRecord); 108 } 109 110 public void aaddAnswerInProvinceRecords(CallRecord callRecord) { 111 answerInProvinceRecords.add(callRecord); 112 } 113 114 public void addAnswerInLandRecords(CallRecord callRecord) { 115 answerInLandRecords.add(callRecord); 116 } 117 118 public void addSendMessageRecords(MessageRecord callRecord) { 119 sendMessageRecords.add(callRecord); 120 } 121 122 public void addReceiveMessageRecords(MessageRecord callRecord) { 123 receiveMessageRecords.add(callRecord); 124 } 125 126 public ArrayList<CallRecord> getCallingInCityRecords() { 127 return callingInCityRecords; 128 } 129 130 public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) { 131 this.callingInCityRecords = callingInCityRecords; 132 } 133 134 public ArrayList<CallRecord> getCallingInProvinceRecords() { 135 return callingInProvinceRecords; 136 } 137 138 public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) { 139 this.callingInProvinceRecords = callingInProvinceRecords; 140 } 141 142 public ArrayList<CallRecord> getCallingInLandRecords() { 143 return callingInLandRecords; 144 } 145 146 public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) { 147 this.callingInLandRecords = callingInLandRecords; 148 } 149 150 public ArrayList<CallRecord> getAnswerInCityRecords() { 151 return answerInCityRecords; 152 } 153 154 public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) { 155 this.answerInCityRecords = answerInCityRecords; 156 } 157 158 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 159 return answerInProvinceRecords; 160 } 161 162 public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) { 163 this.answerInProvinceRecords = answerInProvinceRecords; 164 } 165 166 public ArrayList<CallRecord> getAnswerInLandRecords() { 167 return answerInLandRecords; 168 } 169 170 public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) { 171 this.answerInLandRecords = answerInLandRecords; 172 } 173 174 public ArrayList<MessageRecord> getSendMessageRecords() { 175 return sendMessageRecords; 176 } 177 178 public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) { 179 this.sendMessageRecords = sendMessageRecords; 180 } 181 182 public ArrayList<MessageRecord> getReceiveMessageRecords() { 183 return receiveMessageRecords; 184 } 185 186 public void setReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) { 187 this.receiveMessageRecords = receiveMessageRecords; 188 } 189 190 } 191 192 class LandlinePhoneCharging extends ChargeMode { 193 194 private double monthlyRent = 20; 195 196 public LandlinePhoneCharging() { 197 super(); 198 chargeRules.add(new LandPhoneInCityRule()); 199 chargeRules.add(new LandPhoneInProvinceRule()); 200 chargeRules.add(new LandPhoneInlandRule()); 201 } 202 203 @Override 204 public double calCost(UserRecords userRecords) { 205 double sumCost = 0; 206 for (ChargeRule rule : chargeRules) { 207 sumCost += rule.calCost(userRecords); 208 } 209 return sumCost; 210 } 211 212 @Override 213 public double getMonthlyRent() { 214 return monthlyRent; 215 } 216 217 } 218 219 class MobilePhoneCharging extends ChargeMode { 220 221 private double monthlyRent = 15; 222 223 public MobilePhoneCharging() { 224 super(); 225 chargeRules.add(new MobilePhoneInCityRule()); 226 chargeRules.add(new MobilePhoneInProvinceRule()); 227 chargeRules.add(new MobilePhoneInlandRule()); 228 } 229 230 @Override 231 public double calCost(UserRecords userRecords) { 232 double sumCost = 0; 233 for (ChargeRule rule : chargeRules) { 234 sumCost += rule.calCost(userRecords); 235 } 236 return sumCost; 237 } 238 239 @Override 240 public double getMonthlyRent() { 241 return monthlyRent; 242 } 243 244 } 245 246 class MobilePhoneMassageCharging extends ChargeMode { 247 248 private double monthlyRent = 0; 249 250 public MobilePhoneMassageCharging() { 251 super(); 252 chargeRules.add(new MobilePhoneMessageRule()); 253 } 254 255 @Override 256 public double calCost(UserRecords userRecords) { 257 double sumCost = 0; 258 for (ChargeRule rule : chargeRules) { 259 sumCost += rule.calCost(userRecords); 260 } 261 return sumCost; 262 } 263 264 @Override 265 public double getMonthlyRent() { 266 return monthlyRent; 267 } 268 269 } 270 271 class Inputdeal { 272 273 public int check(String input) { 274 if (input.matches("[u]-0791[0-9]{7,8}\\s[0]") || input.matches("[u]-1[0-9]{10}\\s[13]")) { 275 return 1; 276 } else if (input.matches("[m]-1[0-9]{10}\\s" + "1[0-9]{10}\\s" + "[0-9a-zA-Z\\s\\.,]+")) { 277 return 2; 278 } 279 return 0; 280 } 281 282 public void writeUser(ArrayList<User> users, String input) { 283 User usernew = new User(); 284 String[] inputs = input.split(" "); 285 String num = inputs[0].substring(2); 286 for (User i : users) { 287 if (i.getNumber().equals(num)) { 288 return; 289 } 290 } 291 usernew.setNumber(num); 292 int mode = Integer.parseInt(inputs[1]); 293 if (mode == 0) { 294 usernew.setChargeMode(new LandlinePhoneCharging()); 295 } else if (mode == 1) { 296 usernew.setChargeMode(new MobilePhoneCharging()); 297 } else if (mode == 3) { 298 usernew.setChargeMode(new MobilePhoneMassageCharging()); 299 } 300 users.add(usernew); 301 } 302 303 public void writeRecord(ArrayList<User> users, String input) { 304 String[] inputs = input.split(" "); 305 inputs[0] = inputs[0].substring(2); 306 307 User callu = null, answeru = null; 308 309 String out = inputs[0]; 310 String in = ""; 311 if (inputs.length == 6) { 312 in = inputs[1]; 313 } else if (inputs.length == 7) { 314 in = inputs[1]; 315 } else if (inputs.length == 8) { 316 in = inputs[2]; 317 } else { 318 in = inputs[1]; 319 } 320 321 for (User i : users) { 322 if (i.getNumber().equals(out)) { 323 callu = i; 324 } 325 if (i.getNumber().equals(in)) { 326 answeru = i; 327 } 328 if (callu != null && answeru != null) { 329 break; 330 } 331 } 332 333 if (input.charAt(0) == 'm') { 334 MessageRecord messageRecord = new MessageRecord(input); 335 if (callu != null) { 336 callu.getUserRecords().addSendMessageRecords(messageRecord); 337 ; 338 } 339 if (answeru != null) { 340 callu.getUserRecords().addReceiveMessageRecords(messageRecord); 341 } 342 } 343 344 } 345 346 } 347 348 abstract class CommunicationRecord { 349 protected String callingNumber; 350 protected String answerNumbe; 351 352 public String getCallingNumber() { 353 return callingNumber; 354 } 355 356 public void setCallingNumber(String callingNumber) { 357 this.callingNumber = callingNumber; 358 } 359 360 public String getAnswerNumbe() { 361 return answerNumbe; 362 } 363 364 public void setAnswerNumbe(String answerNumbe) { 365 this.answerNumbe = answerNumbe; 366 } 367 368 } 369 370 abstract class ChargeRule { 371 372 abstract public double calCost(UserRecords userRecords); 373 374 } 375 376 class CallRecord extends CommunicationRecord { 377 private Date startTime; 378 private Date endTime; 379 private String callingAddressAreaCode; 380 private String answerAddressAreaCode; 381 382 public String getCallType() { 383 String type = ""; 384 if (callingAddressAreaCode.equals("0791")) { 385 type = type.concat("1"); 386 } else if (callingAddressAreaCode.matches("^079[023456789]$") || callingAddressAreaCode.equals("0701")) { 387 type = type.concat("2"); 388 } else { 389 type = type.concat("3"); 390 } 391 392 if (answerAddressAreaCode.equals("0791")) { 393 type = type.concat("1"); 394 } else if (answerAddressAreaCode.matches("^079[023456789]$") || answerAddressAreaCode.equals("0701")) { 395 type = type.concat("2"); 396 } else { 397 type = type.concat("3"); 398 } 399 400 return type; 401 } 402 403 public CallRecord(String[] inputs) { 404 super(); 405 406 char type = inputs[0].charAt(0); 407 408 String sd = null, st = null, ed = null, et = null; 409 410 if (type == 't') { 411 if (inputs.length == 6) { 412 sd = inputs[2]; 413 st = inputs[3]; 414 ed = inputs[4]; 415 et = inputs[5]; 416 callingAddressAreaCode = inputs[0].substring(0, 4); 417 answerAddressAreaCode = inputs[1].substring(0, 4); 418 } else if (inputs.length == 7) { 419 sd = inputs[3]; 420 st = inputs[4]; 421 ed = inputs[5]; 422 et = inputs[6]; 423 if (inputs[0].charAt(0) != '0') { 424 if (inputs[2].length() == 10) { 425 answerAddressAreaCode = inputs[2].substring(0, 3); 426 } else { 427 answerAddressAreaCode = inputs[2].substring(0, 4); 428 } 429 callingAddressAreaCode = inputs[1]; 430 } else { 431 if (inputs[0].length() == 10) { 432 callingAddressAreaCode = inputs[0].substring(0, 3); 433 } else { 434 callingAddressAreaCode = inputs[0].substring(0, 4); 435 } 436 answerAddressAreaCode = inputs[2]; 437 } 438 } else if (inputs.length == 8) { 439 sd = inputs[4]; 440 st = inputs[5]; 441 ed = inputs[6]; 442 et = inputs[7]; 443 callingAddressAreaCode = inputs[1]; 444 answerAddressAreaCode = inputs[3]; 445 } 446 } else if (type == 'm') { 447 448 } 449 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault()); 450 try { 451 startTime = simpleDateFormat.parse(sd + " " + st); 452 endTime = simpleDateFormat.parse(ed + " " + et); 453 } catch (ParseException e) { 454 } 455 456 } 457 458 public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) { 459 super(); 460 this.startTime = startTime; 461 this.endTime = endTime; 462 this.callingAddressAreaCode = callingAddressAreaCode; 463 this.answerAddressAreaCode = answerAddressAreaCode; 464 } 465 466 public Date getStartTime() { 467 return startTime; 468 } 469 470 public void setStartTime(Date startTime) { 471 this.startTime = startTime; 472 } 473 474 public Date getEndTime() { 475 return endTime; 476 } 477 478 public void setEndTime(Date endTime) { 479 this.endTime = endTime; 480 } 481 482 public String getCallingAddressAreaCode() { 483 return callingAddressAreaCode; 484 } 485 486 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 487 this.callingAddressAreaCode = callingAddressAreaCode; 488 } 489 490 public String getAnswerAddressAreaCode() { 491 return answerAddressAreaCode; 492 } 493 494 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 495 this.answerAddressAreaCode = answerAddressAreaCode; 496 } 497 } 498 499 abstract class CallChargeRule extends ChargeRule { 500 501 } 502 503 class LandPhoneInCityRule extends CallChargeRule { 504 505 @Override 506 public double calCost(UserRecords userRecords) { 507 double sumCost = 0; 508 for (CallRecord call : userRecords.getCallingInCityRecords()) { 509 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 510 if (distanceS < 0) { 511 continue; 512 } 513 double distanceM = (int) distanceS / 60; 514 if (distanceS % 60 != 0) { 515 distanceM += 1; 516 } 517 if (call.getCallType().equals("11")) { 518 sumCost += distanceM * 0.1; 519 } else if (call.getCallType().equals("12")) { 520 sumCost += distanceM * 0.3; 521 } else if (call.getCallType().equals("13")) { 522 sumCost += distanceM * 0.6; 523 } 524 } 525 return sumCost; 526 } 527 528 } 529 530 class LandPhoneInlandRule extends CallChargeRule { 531 532 @Override 533 public double calCost(UserRecords userRecords) { 534 double sumCost = 0; 535 for (CallRecord call : userRecords.getCallingInLandRecords()) { 536 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 537 if (distanceS < 0) { 538 continue; 539 } 540 double distanceM = (int) distanceS / 60; 541 if (distanceS % 60 != 0) { 542 distanceM += 1; 543 } 544 sumCost += distanceM * 0.6; 545 } 546 return sumCost; 547 } 548 549 } 550 551 class LandPhoneInProvinceRule extends CallChargeRule { 552 553 @Override 554 public double calCost(UserRecords userRecords) { 555 double sumCost = 0; 556 for (CallRecord call : userRecords.getCallingInProvinceRecords()) { 557 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 558 if (distanceS < 0) { 559 continue; 560 } 561 double distanceM = (int) distanceS / 60; 562 if (distanceS % 60 != 0) { 563 distanceM += 1; 564 } 565 sumCost += distanceM * 0.3; 566 } 567 return sumCost; 568 } 569 570 } 571 572 class MobilePhoneInCityRule extends CallChargeRule { 573 574 @Override 575 public double calCost(UserRecords userRecords) { 576 double sumCost = 0; 577 for (CallRecord call : userRecords.getCallingInCityRecords()) { 578 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 579 if (distanceS < 0) { 580 continue; 581 } 582 double distanceM = (int) distanceS / 60; 583 if (distanceS % 60 != 0) { 584 distanceM += 1; 585 } 586 if (call.getCallType().equals("11")) { 587 sumCost += distanceM * 0.1; 588 } else if (call.getCallType().equals("12")) { 589 sumCost += distanceM * 0.2; 590 } else if (call.getCallType().equals("13")) { 591 sumCost += distanceM * 0.3; 592 } 593 594 } 595 return sumCost; 596 } 597 598 } 599 600 class MobilePhoneInlandRule extends CallChargeRule { 601 602 @Override 603 public double calCost(UserRecords userRecords) { 604 double sumCost = 0; 605 for (CallRecord call : userRecords.getCallingInLandRecords()) { 606 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 607 if (distanceS < 0) { 608 continue; 609 } 610 double distanceM = (int) distanceS / 60; 611 if (distanceS % 60 != 0) { 612 distanceM += 1; 613 } 614 sumCost += distanceM * 0.6; 615 } 616 for (CallRecord call : userRecords.getAnswerInLandRecords()) { 617 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 618 if (distanceS < 0) { 619 continue; 620 } 621 double distanceM = (int) distanceS / 60; 622 if (distanceS % 60 != 0) { 623 distanceM += 1; 624 } 625 sumCost += distanceM * 0.3; 626 } 627 return sumCost; 628 } 629 630 } 631 632 class MobilePhoneInProvinceRule extends CallChargeRule { 633 634 @Override 635 public double calCost(UserRecords userRecords) { 636 double sumCost = 0; 637 for (CallRecord call : userRecords.getCallingInProvinceRecords()) { 638 double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000; 639 if (distanceS < 0) { 640 continue; 641 } 642 double distanceM = (int) distanceS / 60; 643 if (distanceS % 60 != 0) { 644 distanceM += 1; 645 } 646 if (call.getCallType().equals("21")) { 647 sumCost += distanceM * 0.3; 648 } else if (call.getCallType().equals("22")) { 649 sumCost += distanceM * 0.3; 650 } else if (call.getCallType().equals("23")) { 651 sumCost += distanceM * 0.3; 652 } 653 } 654 return sumCost; 655 } 656 657 } 658 659 class MobilePhoneMessageRule extends CallChargeRule { 660 661 @Override 662 public double calCost(UserRecords userRecords) { 663 double sumCost = 0; 664 int number = 0; 665 for (MessageRecord m : userRecords.getSendMessageRecords()) { 666 int length = m.getMessage().length(); 667 if (length <= 10) { 668 number++; 669 } else { 670 number += length / 10; 671 if (length % 10 != 0) { 672 number++; 673 } 674 } 675 } 676 if (number <= 3) { 677 sumCost = number * 0.1; 678 } else if (number <= 5) { 679 sumCost = 0.3 + 0.2 * (number - 3); 680 } else { 681 sumCost = 0.7 + 0.3 * (number - 5); 682 } 683 return sumCost; 684 } 685 686 } 687 688 class MessageRecord extends CommunicationRecord { 689 690 private String message; 691 692 public MessageRecord(String input) { 693 super(); 694 this.message = input.substring(26); 695 } 696 697 public String getMessage() { 698 return message; 699 } 700 701 public void setMessage(String message) { 702 this.message = message; 703 } 704 } 705 706 class User { 707 708 private UserRecords userRecords = new UserRecords(); 709 private double balance = 100; 710 private ChargeMode chargeMode; 711 private String number; 712 713 public double calCost() { 714 return chargeMode.calCost(userRecords); 715 } 716 717 public double calBalance() { 718 return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords); 719 } 720 721 public UserRecords getUserRecords() { 722 return userRecords; 723 } 724 725 public void setUserRecords(UserRecords userRecords) { 726 this.userRecords = userRecords; 727 } 728 729 public ChargeMode getChargeMode() { 730 return chargeMode; 731 } 732 733 public void setChargeMode(ChargeMode chargeMode) { 734 this.chargeMode = chargeMode; 735 } 736 737 public String getNumber() { 738 return number; 739 } 740 741 public void setNumber(String number) { 742 this.number = number; 743 } 744 745 } 746 747 class Outputtool { 748 749 @SuppressWarnings("deprecation") 750 public void output(double out) { 751 // java.text.DecimalFormat df=new java.text.DecimalFormat("#.##"); 752 // String a=df.format(out); 753 // System.out.print(a); 754 BigDecimal numb = new BigDecimal(out); 755 out = numb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); 756 System.out.print(out); 757 } 758 }
8_2.编写一个类Shop(商店)、内部类InnerCoupons(内部购物券)
编写一个类Shop(商店),该类中有一个成员内部类InnerCoupons(内部购物券),可以用于购买该商店的牛奶(假设每箱牛奶售价为50元)。要求如下:
(1)Shop类中有私有属性milkCount(牛奶的箱数,int类型)、公有的成员方法setMilkCount( )和getMilkCount( )分别用于设置和获取牛奶的箱数。
(2)成员内部类InnerCoupons,有公有属性value(面值,int类型),一个带参数的构造方法可以设定购物券的面值value,一个公有的成员方法buy( )要求输出使用了面值为多少的购物券进行支付,同时使商店牛奶的箱数减少value/50。
(3)Shop类中还有成员变量coupons50(面值为50元的内部购物券,类型为InnerCoupons)、coupons100(面值为100元的内部购物券,类型为InnerCoupons)。
(4)在Shop类的构造方法中,调用内部类InnerCoupons的带参数的构造方法分别创建上面的购物券coupons50、coupons100。
在测试类Main中,创建一个Shop类的对象myshop,从键盘输入一个整数(大于或等于3),将其设置为牛奶的箱数。假定有顾客分别使用了该商店面值为50的购物券、面值为100的购物券各消费一次,分别输出消费后商店剩下的牛奶箱数。
输入格式:
输入一个大于或等于3的整数。
输出格式:
使用了面值为50的购物券进行支付
牛奶还剩XX箱
使用了面值为100的购物券进行支付
牛奶还剩XX箱
输入样例:
在这里给出一组输入。例如:
5
输出样例:
在这里给出相应的输出。例如:
使用了面值为50的购物券进行支付 牛奶还剩4箱 使用了面值为100的购物券进行支付 牛奶还剩2箱
代码:
1 import java.util.Scanner; 2 public class Main { 3 public static void main(String[] args) { 4 Scanner input = new Scanner(System.in); 5 Shop myshop = new Shop(input.nextInt()); 6 myshop.coupons50.buy(); 7 System.out.println("牛奶还剩" + myshop.getMilkCount() + "箱"); 8 myshop.coupons100.buy(); 9 System.out.println("牛奶还剩" + myshop.getMilkCount() + "箱"); 10 } 11 } 12 13 class Shop{//商店类 14 private int milkCount;//牛奶的箱数 15 class InnerCoupons{//(内部购物券) 16 int value;//购物券的面值 17 18 public InnerCoupons(int value) {//带参数的构造方法,可以设置购物券的面值 19 this.value = value; 20 } 21 public void buy(){ 22 System.out.println("使用了面值为"+ value +"的购物券进行支付"); 23 milkCount = milkCount - value / 50; 24 } 25 } 26 InnerCoupons coupons50 = new InnerCoupons(50);//50元的购物券 27 InnerCoupons coupons100 = new InnerCoupons(100);//100元的购物券 28 29 public Shop(int milkCount) {//牛奶箱数 30 this.milkCount = milkCount; 31 } 32 33 public int getMilkCount() {//获取牛奶的箱数 34 return milkCount; 35 } 36 37 public void setMilkCount(int milkCount) {//设置牛奶的箱数 38 this.milkCount = milkCount; 39 } 40 }
分析:
这题主要成员内部类的使用,其中有点难度的就是那个50和100的购物券那个地方当时,本来是想在主函数里面设置50和100的购物券,结果一直报错,后来就放在shop类里面直接设置,然后在主函数直接调用。
8_3.动物发声模拟器(多态)
设计一个动物发生模拟器,用于模拟不同动物的叫声。比如狮吼、虎啸、狗旺旺、猫喵喵……。
定义抽象类Animal,包含两个抽象方法:获取动物类别getAnimalClass()、动物叫shout();
然后基于抽象类Animal定义狗类Dog、猫类Cat和山羊Goat,用getAnimalClass()方法返回不同的动物类别(比如猫,狗,山羊),用shout()方法分别输出不同的叫声(比如喵喵、汪汪、咩咩)。
最后编写AnimalShoutTest类测试,输出:
猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩
其中,在AnimalShoutTestMain类中,用speak(Animal animal){}方法输出动物animal的叫声,在main()方法中调用speak()方法,分别输出猫、狗和山羊对象的叫声。
请在下面的【】处添加代码。
//动物发生模拟器. 请在下面的【】处添加代码。
public class AnimalShoutTest2 {
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()
【】
}
//定义抽象类Animal
【】class Animal{
【】
}
//基于Animal类,定义猫类Cat,并重写两个抽象方法
class Cat 【】{
【】
【】
}
//基于Animal类,定义狗类Dog,并重写两个抽象方法
class Dog 【】{
【】
【】
}
//基于Animal类,定义山羊类Goat,并重写两个抽象方法
class Goat 【】{
【】
【】
}
输入样例:
输出样例:
猫的叫声:喵喵 狗的叫声:汪汪 山羊的叫声:咩咩
代码:
1 //动物发生模拟器. 请在下面的【】处添加代码。 2 public class Main{ 3 public static void main(String[] args){ 4 Cat cat = new Cat(); 5 Dog dog = new Dog(); 6 Goat goat = new Goat(); 7 speak(cat); 8 speak(dog); 9 speak(goat); 10 } 11 //定义静态方法speak() 12 static void speak(Animal animal){ 13 System.out.println(animal.getAnimalClass() + "的叫声:" + animal.shout()); 14 } 15 } 16 17 18 19 20 21 22 //定义抽象类Animal 23 abstract class Animal{ 24 abstract String getAnimalClass(); 25 abstract String shout(); 26 } 27 //基于Animal类,定义猫类Cat,并重写两个抽象方法 28 class Cat extends Animal{ 29 30 31 @Override 32 String getAnimalClass() { 33 return "猫"; 34 } 35 36 @Override 37 String shout() { 38 return "喵喵"; 39 } 40 } 41 //基于Animal类,定义狗类Dog,并重写两个抽象方法 42 class Dog extends Animal{ 43 44 @Override 45 String getAnimalClass() { 46 return "狗"; 47 } 48 49 @Override 50 String shout() { 51 return "汪汪"; 52 } 53 } 54 //基于Animal类,定义山羊类Goat,并重写两个抽象方法 55 class Goat extends Animal{ 56 57 @Override 58 String getAnimalClass() { 59 return "山羊"; 60 } 61 62 @Override 63 String shout() { 64 return "咩咩"; 65 } 66 }
分析:
这题没什么说的,比较简单。
三.踩坑心得
其实还好但是知识点有很多盲区比如知识点总结接口的注意事项:如果多个接口含有相同的抽象方法,则直接重写一回即可如果没有覆盖重写全部的,必须是抽象类接口中有相同的默认方法必须要重写,抽象类中也要重写一个类如果直接父类的方法与接口的默认方法冲突,优先使用父类的方法。多态的注意事项有继承关系子类重写父类方法子类引用指向父类对象,子类特有方法不能直接表达出来,需要子类和父类都有。抽象类的注意事项和知识点abstract(抽象类):它是一个类,离不开extends(继承),但extends是单继承,不能继承多个类,有局限性在抽象类中可以写普通方法,抽象方法必须写在抽象类中,不能实例化抽象类,只能靠它的子类去实现它,抽象类是受约束的。使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。
四.改进建议
我感觉还是有点难了,题目可能来说挺不错的,但是一些细节还是没处理好,比如测试点,有些就挺恶心的。五.总结
1.函数与变量的调用上,代码耦合度高,调用关系太乱。
2.代码注释少,隔段时间就会看不懂代码,增加工作难度,习惯不好
3.字符串输入尽量用next() 代替 nextLine() ,因为next()会过滤掉无用的换行符,减少输入类型的不匹配的问题。
4.收获:通过电信计费让我更加懂得了如何使用正则表达式控制输入,及如何记录时间及计算时间间隔,会用新的方法处理不满一分钟的情况等,对类的设计也更加合理,相比从前编程的逻辑也更加清晰,类的使用更加顺手,处理类间关系时更加完善。对容器的有关用法更加熟练,使用继承关系,编写抽象方法,不同子类实现抽象方法,对这类的编写。

浙公网安备 33010602011771号