BLOG-3_JavaHomework_Summary

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));
    }
}

代码类图

BLOG-3_JavaHomework_Summary

分析

个人的思路是将用户和记录读入后,分别存于容器,再将数据传到一个 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/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 2020年度钻石C++C学习笔记(3)–《博学谷》

    1.Unix/Linux操作系统介绍 1.1 操作系统的作用 1.1.1 操作系统的目标 l 方便:使计算机系统易于使用 l 有效:以更有效的方式使用计算机系统资源 l 扩展:方便…

    Java 2023年6月7日
    086
  • 计算机基础知识

    计算机网络基础 网络层次划分 OSI七层划分 TCP/IP4层模型、5层模型和OSI七层模型的差别 物理层 物理层的作用:连接不同的物理设备,传输比特流。该层为上层协议提供了一个传…

    Java 2023年6月13日
    075
  • Oracle数据库😊

    sqlplus常用命令 连接数据库:conn 用户名/密码@网络服务标识[as sysdba] 断开数据库连接: 断开和oracle的连接但是不退出sqlplus窗口 区别:sta…

    Java 2023年6月15日
    049
  • Nginx+Keepalived实现站点高可用

    http://seanlook.com/2015/05/18/nginx-keepalived-ha/ http://blog.csdn.net/conquer0715/artic…

    Java 2023年5月30日
    072
  • 2022-8-26 jq简单了解

    Query 是一个 JavaScript 函数库。 jQuery 是一个轻量级的”写的少,做的多”的 JavaScript 库。jQuery 库包含以下功能…

    Java 2023年6月13日
    072
  • IDEA对数据库、表、记录的(增删改查可视化操作)、数据库安全性问题的演示

    演示脏读 一个事物里面读到了另外一个事物没有提交的数据: read uncommitted 1.开启A,B窗口 2.分别查询A,B的隔离级别 select @@tx_isolati…

    Java 2023年6月15日
    069
  • 反射 构造函数 参数

    引用:http://xiaohuafyle.iteye.com/blog/1607258 通过反射创建新的类示例,有两种方式:Class.newInstance()Construc…

    Java 2023年5月30日
    071
  • JAVA规则引擎JSR-94笔札

    JSR-94 是由JCP(Java Community Process)组织所制定的java规则引擎API的java请求规范。它主要定义了规则引擎在java运行时的一些API,指导…

    Java 2023年6月15日
    076
  • 线性回归大结局(岭(Ridge)、 Lasso回归原理、公式推导),你想要的这里都有

    本文已参与「新人创作礼」活动,一起开启掘金创作之路。 线性模型简介 所谓线性模型就是通过数据的线性组合来拟合一个数据,比如对于一个数据 (X) [X = (x_1, x_2, x_…

    Java 2023年6月8日
    076
  • 国际化异常:No message found under code ‘xxx’ for locale ‘zh_CN’ 解决办法

    导致该异常可能的原因: 没有配置 LocaleChangeInterceptor 拦截器。 基于 session 获取用户语言设定决定语言区域,必须配置拦截器。 Spring MV…

    Java 2023年6月13日
    072
  • Java new Date() 获取的时间不正确 【已解决】

    ▌问题描述new Date()获取正确,使用TimeUtils.timeInUTC()转换日期格式后,时间早了比北京时间晚了8小时 ▌原因分析时区不正确,TimeUtils默认使用…

    Java 2023年5月29日
    0112
  • MyBatis实现动态排序方法

    问题: MyBatis想实现动态排序,即自己传排序字段以及排序方式,但是按正常传参会导致查询失败。 因为上面的sql会被处理成如下,即参数会被加上引号当字符串处理。 解决方法: 使…

    Java 2023年5月30日
    073
  • SpringBoot内置Tomcat启动原理源码分析

    1、获取SpringBoot内置Tomcat自动配置类: 在SpringBoot项目中引入spring-boot-starter-web依赖,就默认使用Tomcat容器,该依赖中引…

    Java 2023年6月7日
    0105
  • 负载均衡

    前言 本文基于Dubbo2.6.x版本,中文注释版源码已上传github:xiaoguyu/dubbo 负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)…

    Java 2023年6月16日
    091
  • JAVA变量、常量以及其命名规范

    变量 变量即可以变化的量 Java是一种强类型语言,每个变量都必须声明其类型。 Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。 常量 常量(Consta…

    Java 2023年6月9日
    075
  • Feign源码解析系列-核心初始化

    开始 初始化Feign客户端当然是整个过程中的核心部分,毕竟初始化完毕就等着调用了,初始化时候准备的什么,流程就走什么。 内容 从上一篇中,我们已经知道,对于扫描到的每一个有@Fe…

    Java 2023年6月13日
    089
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球