java第4-6次作业总结

一.前言:

  我认为这三次的题目整体难度适中,与类有关的设计题目都有提示。主要的知识点当然是面向对象的六个字:封装、继承、多态。并且再次加深学习了正则表达式(好用确实好用)。

  我对封装、继承、多态的理解:1、封装是隐藏对象的属性和实现细节,对外提供公共的访问方式,以防止数据的随意访问和修改;2、继承是通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类;3、接口的多种不同的实现方式即为多态。

 

二.设计与分析:

   ①题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较

    这两个题目基本是一样的,不过题目是两种不同的类设计,如下图:

题目集4(7-2)的类图设计

 

 

题目集5(7-4)的类图设计

 

 

 

做题的时候本人没有注意,都是使用的第一种类设计过的题目。以下给出相关代码以及所实现的类图:

 

代码如下:

 

 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        switch(in.nextInt()) {
        case 1:
            DateUtil date = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt());
            if(date.checkInputValidity()) {
                date.getNextNDays(in.nextInt());
                System.out.println(date.showDate());
            }
            else {
                System.out.println("Wrong Format");
            }
            break;
        case 2:
            date = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt());
            if(date.checkInputValidity()) {
                date.getPreviousNDays(in.nextInt());
                System.out.println(date.showDate());
            }
            else {
                System.out.println("Wrong Format");
            }
            break;
        case 3:
            DateUtil date1 = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt());
            DateUtil date2 = new DateUtil(in.nextInt(), in.nextInt(), in.nextInt());
            if(date1.checkInputValidity()&&date2.checkInputValidity()) {
                System.out.println(date1.getDaysofDates(date2));
            }
            else {
                System.out.println("Wrong Format");
            }
            break;
        default:System.out.println("Wrong Format");
        }
        
        in.close();
    }
}
    
class DateUtil{
    private Day day = new Day();
    
    DateUtil(){
    }
    DateUtil(int y, int m, int d){
        this.day.setDayValue(d);
        this.day.getMonth().setMonthValue(m);
        this.day.getMonth().getYear().setyearValue(y);
    }
    
    Day getDay() {
        return day;
    }
    void setDay(Day day) {
        this.day = day;
    }
    
    boolean checkInputValidity() {//校验数据的合法性
        if(this.day.getMonth().getYear().validate()&&this.day.getMonth().validate()&&this.day.validate()) {
            return true;
        }
        else {
            return false;
        }
    }
    boolean compareDates(DateUtil date) {//比较两个日期的大小,比date大返回true
        if(this.day.getMonth().getYear().getyearValue()>date.day.getMonth().getYear().getyearValue()) {
            return true;
        }
        else if(this.day.getMonth().getYear().getyearValue()<date.day.getMonth().getYear().getyearValue()){
            return false;
        }
        else {
            if(this.day.getMonth().getMonthValue()>date.day.getMonth().getMonthValue()) {
                return true;
            }
            else if(this.day.getMonth().getMonthValue()<date.day.getMonth().getMonthValue()) {
                return false;
            }
            else {
                if(this.day.getDayValue()>date.day.getDayValue()) {
                    return true;
                }
                else if(this.day.getDayValue()<date.day.getDayValue()) {
                    return false;
                }
                else {//日期相等
                    return false;
                }
            }
        }
    }
    boolean equalTwoDates(DateUtil date) {//判断两个日期是否相等
        if(this.day.getDayValue()==date.day.getDayValue()) {
            if(this.day.getMonth().getMonthValue()==date.day.getMonth().getMonthValue()) {
                if(this.day.getMonth().getYear().getyearValue()==date.day.getMonth().getYear().getyearValue()) {
                    return true;
                }
            }
        }
        return false;
    }
    String showDate() {//日期值格式化
        return String.valueOf(this.day.getMonth().getYear().getyearValue())+"-"+String.valueOf(this.day.getMonth().getMonthValue())+"-"+String.valueOf(this.day.getDayValue());
    }
    DateUtil getNextNDays(int n) {//求下n天
        for(int i = 0; i < n; i++) {
            this.day.dayIncrement();
            if(!this.day.validate()) {
                this.day.getMonth().monthIncrement();
                if(!this.day.getMonth().validate()) {
                    this.day.getMonth().getYear().yearIncrement();
                    this.day.getMonth().resetMin();
                }
                this.day.resetMin();
            }
        }
        return this;
    }
    DateUtil getPreviousNDays(int n) {//求前n天
        for(int i = 0; i < n; i++) {
            this.day.dayReduction();
            if(!this.day.validate()) {
                this.day.getMonth().monthReduction();
                if(!this.day.getMonth().validate()) {
                    this.day.getMonth().getYear().yearReduction();
                    this.day.getMonth().resetMax();
                }
                this.day.resetMax();
            }
        }
        return this;
    }
    int getDaysofDates(DateUtil date) {//求两个日期之间的天数
        int sum = 0;
        while(!this.equalTwoDates(date)) {
            sum++;
            if(this.compareDates(date)) {
                date.getNextNDays(1);
            }
            else {
                date.getPreviousNDays(1);
            }
        }
        return sum;
    }
}

class Year{
    private int yearValue;
    
    Year(){
    }
    Year(int yearValue){
        this.yearValue = yearValue;
    }
    
    int getyearValue() {
        return yearValue;
    }
    void setyearValue(int yearValue) {
        this.yearValue = yearValue;
    }
    
    boolean isLeapYear() {//判断是否为闰年
        if((this.yearValue%4==0&&this.yearValue%100!=0)||this.yearValue%400==0) {
            return true;
        }
        else {
            return false;
        }
    }
    boolean validate() {//校验数据合法性
        if(this.yearValue>=1900&&this.yearValue<=2050) {
            return true;
        }
        else {
            return false;
        }
    }
    void yearIncrement() {//年份增一
        this.yearValue++;
    }
    void yearReduction() {//年份减一
        this.yearValue--;
    }
}

class Month{
    private int monthValue;
    private Year year = new Year();
    
    Month(){
    }
    Month(int yearValue, int monthValue){
        this.monthValue = monthValue;
        this.year.setyearValue(yearValue);
    }
    
    int getMonthValue() {
        return monthValue;
    }
    void setMonthValue(int monthValue) {
        this.monthValue = monthValue;
    }
    Year getYear() {
        return year;
    }
    void setYear(Year year) {
        this.year = year;
    }
    
    void resetMin() {//月份复位(1)
        this.monthValue = 1;
    }
    void resetMax() {//月份设置为12
        this.monthValue = 12;
    }
    boolean validate() {//校验数据合法性
        if(this.monthValue>=1&&this.monthValue<=12) {
            return true;
        }
        else {
            return false;
        }
    }
    void monthIncrement() {//月份增一
        this.monthValue++;
    }
    void monthReduction() {//月份减一
        this.monthValue--;
    }
}

class Day{
    private int dayValue;
    private Month month = new Month();
    private int[] mon_maxnum = new int[] {31,28,31,30,31,30,31,31,30,31,30,31};
    
    Day(){
    }
    Day(int yearValue, int monthValue, int dayValue){
        this.dayValue = dayValue;
        this.month.setMonthValue(monthValue);
        this.month.getYear().setyearValue(yearValue);;
    }
    
    int getDayValue() {
        return dayValue;
    }
    void setDayValue(int dayValue) {
        this.dayValue = dayValue;
    }
    Month getMonth() {
        return month;
    }
    void setMonth(Month month) {
        this.month = month;
    }
    
    void resetMin() {//日期复位(1)
        this.dayValue = 1;
    }
    void resetMax() {//日期设为该月最大值
        if(this.month.getYear().isLeapYear()) {
            this.mon_maxnum[1] = 29;
        }
        this.dayValue = this.mon_maxnum[this.month.getMonthValue()-1];
    }
    boolean validate() {//校验数据的合法性
        if(this.month.getYear().isLeapYear()) {
            this.mon_maxnum[1] = 29;
        }
        else {
            this.mon_maxnum[1] = 28;
        }
        if(this.dayValue>=1&&this.dayValue<=this.mon_maxnum[this.month.getMonthValue()-1]) {
            return true;
        }
        else {
            return false;
        }
    }
    void dayIncrement() {//日期增一
        this.dayValue++;
    }
    void dayReduction() {//日期减一
        this.dayValue--;
    }
}
View Code

 

类图以及分析图如下:

 

 

 

 写的不是很好圈复杂度还是超了点。

这题写的方法用在另一题开始在数据最大点没有过,多次调试发现将for循环改为while循环即可通过(奇怪的知识又增加了,java中while循环比for快多了)

 

 由于没有用第二种类设计写,在这里脑测一下:我感觉我比较喜欢第二种的类设计,第一种给我的感觉就是无限套娃,在需要用到更深的类方法要写出很长一句,不方便阅读等。第一种线性,层次清晰,第二种实用方便。

 

 ②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)

这三题主要是类的继承和多态性,以及接口的运用。题目集6(7-6)用了一个接口,无属性,只有一个GetArea(求面积)的抽象方法,题目集4(7-3)中Ball继承Circle,Box继承Rectangle,而Circle与Rectangle都是继承Shape类。

 

 题目集4(7-3)的源码以及类图如下:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        /*
         * 1 圆半径
            2 矩形宽、长
            3 球半径
            4 立方体宽、长、高
         */
        switch(in.nextInt()) {
        case 1:double radius = in.nextDouble();
            if(radius>0) {
                Circle cir = new Circle(radius);
                System.out.printf("Circle's area:%.2f\n", cir.getArea());
            }
            else {
                System.out.println("Wrong Format");
            }
            break;
        case 2:double width = in.nextDouble(), length = in.nextDouble();
            if(width>0&&length>0) {
                Rectangle rec = new Rectangle(width, length);
                System.out.printf("Rectangle's area:%.2f\n", rec.getArea());
            }
            else {
                System.out.println("Wrong Format");
            }
            break;
        case 3:radius = in.nextDouble();
            if(radius>0) {
                Ball bal = new Ball(radius);
                System.out.printf("Ball's surface area:%.2f\n", bal.getArea());
                System.out.printf("Ball's volume:%.2f\n", bal.getVolume());
            }
            else {
                System.out.println("Wrong Format");
            }
            break;
        case 4:width = in.nextDouble(); length = in.nextDouble();double height = in.nextDouble();
        if(width>0&&length>0&&height>0) {
            Box box = new Box(width, length, height);
            System.out.printf("Box's surface area:%.2f\n", box.getArea());
            System.out.printf("Box's volume:%.2f\n", box.getVolume());
        }
        else {
            System.out.println("Wrong Format");
        }
            break;
        default:System.out.println("Wrong Format");
        }
        
        in.close();
    }
}
    
class Shape{
    Shape(){
        System.out.println("Constructing Shape");
    }
    
    public double getArea() {//求图形面积
        return 0.0;
    }
}

class Circle extends Shape{
    private double radius;
    
    Circle(double radius){
        this.radius = radius;
        System.out.println("Constructing Circle");
    }
    
    public double getArea() {//求圆的面积
        return this.radius*this.radius*Math.PI;
    }

    double getRadius() {
        return radius;
    }

    void setRadius(double radius) {
        this.radius = radius;
    }
}

class Rectangle extends Shape{
    private double width;
    private double length;
    
    Rectangle(double width, double length){
        this.width = width;
        this.length = length;
        System.out.println("Constructing Rectangle");
    }
    
    public double getArea() {//求矩形面积
        return this.length*this.width;
    }

    double getWidth() {
        return width;
    }

    void setWidth(double width) {
        this.width = width;
    }

    double getLength() {
        return length;
    }

    void setLength(double length) {
        this.length = length;
    }
}

class Ball extends Circle{
    Ball(double radius){
        super(radius);
        System.out.println("Constructing Ball");
    }
    
    public double getArea() {//求球的面积
        return 4*Math.PI*super.getRadius()*super.getRadius();
    }
    
    public double getVolume(){//求球体积
        return 4*Math.PI*Math.pow(super.getRadius(), 3)/3;
    }
}

class Box extends Rectangle{
    private double height;
    
    Box(double width, double length, double height){
        super(width, length);
        this.height = height;
        System.out.println("Constructing Box");
    }
    
    public double getArea() {//求矩形面积
        return super.getLength()*super.getWidth()*2+this.height*super.getWidth()*2+super.getLength()*this.height*2;
    }
    
    public double getVolume(){//求立方体体积
        return this.height*super.getWidth()*super.getLength();
    }

    double getHeight() {
        return height;
    }

    void setHeight(double height) {
        this.height = height;
    }
    
}
View Code

 

 

 

 

 题目集6(7-5)的源码以及类图如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        ArrayList<Shape> list = new ArrayList<>();
        int a, b, c;
        a = in.nextInt();
        b = in.nextInt();
        c = in.nextInt();
        
        for(int i = 0; i < a; i++) {
            Circle circle = new Circle(in.nextDouble());
            list.add(circle);
        }
        for(int i = 0; i < b; i++) {
            Rectangle rectangle = new Rectangle(in.nextDouble(), in.nextDouble());
            list.add(rectangle);
        }
        for(int i = 0; i < c; i++) {
            Triangle triangle = new Triangle(in.nextDouble(), in.nextDouble(), in.nextDouble());
            list.add(triangle);
        }
        
        if(a==0&&b==0&&c==0) {
            Data.show(list);
        }
        else if(!Data.validate(list)) {
            System.out.println("Wrong Format");
        }
        else {
            Data.show(list);
        }
        
        in.close();
    }
}
/*
 * 数据处理类
 */
class Data{
    static boolean validate(ArrayList<Shape> list) {//合法性校验
        if(list.size()==0)
            return false;
        for(int i = 0; i < list.size(); i++) {
            if(!list.get(i).validate())
                return false;
        }
        return true;
    }
    static void shapeSort(ArrayList<Shape> list) {//图形排序
        Collections.sort(list, new Comparator<Shape>(){

            @Override
            public int compare(Shape o1, Shape o2) {
                // TODO 自动生成的方法存根
                if(o1.getArea()-o2.getArea()>0)
                    return 1;
                else
                    return -1;
            }
        });
    }
    static double getAllArea(ArrayList<Shape> list) {//面积求和
        double sum = 0;
        for(int i = 0; i < list.size(); i++) {
            sum += list.get(i).getArea();
        }
        return sum;
    }
    static void show(ArrayList<Shape> list) {//输出面积
        System.out.println("Original area:");
        for(int i = 0; i < list.size(); i++) {
            System.out.printf("%.2f ", list.get(i).getArea());
        }
        System.out.printf("\nSum of area:%.2f\n", getAllArea(list));
        
        System.out.println("Sorted area:");
        shapeSort(list);
        for(int i = 0; i < list.size(); i++) {
            System.out.printf("%.2f ", list.get(i).getArea());
        }
        System.out.printf("\nSum of area:%.2f", getAllArea(list));
    }
}
/*
 * 图形类
 */
class Shape{
    Shape(){
    }
    double getArea() {//图形面积
        return 0;
    }
    boolean validate() {//合法性校验
        return true;
    }
    public String toString() {
        return getClass().getName();
    }
}
/*
 * 圆形类,继承图形类
 */
class Circle extends Shape{
    private double radius;
    
    Circle(double radius){
        this.radius = radius;
    }
    boolean validate() {//合法性校验
        if(this.radius>0)
            return true;
        else
            return false;
    }
    double getArea() {//图形面积
        return Math.PI*this.radius*this.radius;
    }
}
/*
 * 矩形类,继承图形类
 */
class Rectangle extends Shape{
    private double width;
    private double length;
    
    Rectangle(double width, double length){
        this.length = length;
        this.width = width;
    }
    boolean validate() {//合法性校验
        if(this.length>0&&this.width>0)
            return true;
        else
            return false;
    }
    double getArea() {//图形面积
        return this.length*this.width;
    }
}
/*
 * 三角形类,继承图形类
 */
class Triangle extends Shape{
    private double side1;
    private double side2;
    private double side3;
    
    Triangle(double side1, double side2, double side3){
        this.side1 = side1;
        this.side2 = side2;
        this.side3 = side3;
    }
    boolean validate() {//合法性校验
        if(this.side1>0&&this.side2>0&&this.side3>0) {
            if(this.side1+this.side2>this.side3
                    && this.side2+this.side3>this.side1
                    && this.side1+this.side3>this.side2)
                return true;
            else
                return false;
        }
        else
            return false;
    }
    double getArea() {//图形面积
        double l = (this.side1+this.side2+this.side3)/2;
        return Math.sqrt(l*(l-this.side1)*(l-this.side2)*(l-this.side3));
    }
}
View Code

 

 

 

 

 

  题目集6(7-6)的源码以及类图如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        Circle circle = new Circle(in.nextDouble());
        Rectangle rectangle = new Rectangle(in.nextDouble(), in.nextDouble());
        
        if(circle.validate()&&rectangle.validate()) {
            System.out.printf("%.2f\n", circle.getArea());
            System.out.printf("%.2f\n", rectangle.getArea());
        }
        else {
            System.out.println("Wrong Format");
        }
        
        in.close();
    }
}
/*
 * 求图形的面积接口
 */
interface GetArea{
    double getArea();
}
/*
 * 圆形类,实现GetArea接口
 */
class Circle implements GetArea{
    private double radius;
    
    Circle(){
    }
    Circle(double radius){
        this.radius = radius;
    }
    
    double getRadius() {
        return radius;
    }
    void setRadius(double radius) {
        this.radius = radius;
    }
    
    boolean validate() {//合法性校验
        if(this.radius>0)
            return true;
        else
            return false;
    }
    public double getArea() {//图形面积
        return Math.PI*this.radius*this.radius;
    }
}
/*
 * 矩形类,实现GetArea接口
 */
class Rectangle implements GetArea{
    private double width;
    private double length;
    
    Rectangle(){
    }
    Rectangle(double width, double length){
        this.length = length;
        this.width = width;
    }
    
    double getWidth() {
        return width;
    }
    void setWidth(double width) {
        this.width = width;
    }
    double getLength() {
        return length;
    }
    void setLength(double length) {
        this.length = length;
    }

    boolean validate() {//合法性校验
        if(this.length>0&&this.width>0)
            return true;
        else
            return false;
    }
    public double getArea() {//图形面积
        return this.length*this.width;
    }
}
View Code

 

 

 

 

 ③对三次题目集中用到的正则表达式技术的分析总结

几次实验下来,正则表达式是个非常好用的东西,本次又学会了正则表达式的贪婪以及非贪婪匹配,单词边界\b。

 

④题目集5(7-4)中Java集合框架应用的分析总结

题目集5(7-4)统计Java程序中关键词的出现次数

 

 

我的思路:设计一个关键字类保存其字符串以及出现次数,一个总关键字类记录所有的关键字。

在去除注释的代码时需要注意,正则匹配的时候使用非贪婪匹配。

(另外,第二个测试点有问题(大佬告诉我的),我是强行过点的)

源码以及类图如下:

import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        Source source = new Source();
        String s;
        while(!(s=in.nextLine()).equals("exit")) {
            source.setAddSb(s+"\n");
        }
        source.getResult();
        //System.out.println(source.setNewSource());
        
        in.close();
    }
}
/*
 * 记录输入的源码
 */
class Source{
    StringBuilder sb = new StringBuilder();

    StringBuilder getSb() {
        return sb;
    }
    void setSb(StringBuilder sb) {
        this.sb = sb;
    }
    
    void setAddSb(String sb) {
        this.sb.append(sb);
    }
    //返回去掉不需要匹配的源码字符串
    String setNewSource() {
        String s = this.sb.toString().replaceAll("//.*", "");
        s = s.replaceAll("/\\*(.*?\\s)*?\\*/", " ");
        s = s.replaceAll("\"(.*?)\"", " ");
        
        return s;
    }
    void getResult() {
        AllKey allkey = new AllKey();
        String s = this.setNewSource();
        if(s.isEmpty()) {
            System.out.println("Wrong Format");
        }
        else {
            for(int i = 0; i < allkey.getNum(); i++) {
                //  \\b单词边界
                Pattern p = Pattern.compile(("\\b"+allkey.getKey()[i].getStr()+"\\b"));
                Matcher m = p.matcher(s);
                
                while(m.find()) {
                    allkey.getKey()[i].sumAdd();
                }
            }
            allkey.show();
        }
    }
}
/*
 * 每个关键字的字符串以及次数统计
 */
class Key{
    private int sum = 0;//关键字出现次数
    private String str = new String();
    
    Key(){
        
    }
    Key(String str){
        this.str = str;
    }
    
    int getSum() {
        return sum;
    }
    void setSum(int sum) {
        this.sum = sum;
    }
    String getStr() {
        return str;
    }
    void setStr(String str) {
        this.str = str;
    }
    
    void sumAdd() {
        this.sum++;
    }
}
/*
 * 所有的关键字
 */
class AllKey{
    private String[] keystr = new String[] {"abstract","assert","boolean","break","byte",
            "case","catch","char","class","continue","default","do","double","else","enum",
            "extends","final","finally","float","for","if","implements","import","int","interface",
            "instanceof","long","native","new","package","private","protected","public","return",
            "short","static","strictfp","super","switch","synchronized","this","throw","throws",
            "transient","try","void","volatile","while","goto","const","true","false","null"};

    private int num = keystr.length;//关键词数目
    private Key[] key = new Key[num];
    
    AllKey() {
        Arrays.sort(keystr);
        for(int i = 0; i < num; i++) {
            key[i] = new Key(keystr[i]);
        }
    }

    String[] getKeystr() {
        return keystr;
    }
    int getNum() {
        return num;
    }
    Key[] getKey() {
        return key;
    }
    
    void show() {
        for(Key i:key) {
            if(i.getSum()>0)
                if(i.getStr().equals("null")&&i.getSum()==1){
                    boolean flag = true;
                    for(Key j:key) {
                        if(j.getSum()==0)
                            flag = false;
                    }
                    if(flag)
                        System.out.println(i.getSum()+"\t"+i.getStr());
                }
                else
                    System.out.println(i.getSum()+"\t"+i.getStr());
        }
    }
}
View Code

 

 

 

 

三.采坑心得:

   题目集5(7-4)统计Java程序中关键词的出现次数这题开始没有学会使用非贪婪匹配,在去除注释的时候debug了好久。

  题目集5(7-4)日期问题中前n天与后n天的最大数据测试的时候超时了,结果发现将for循环改用while循环就能过了(测试下来时间差距还是挺大的)。

 

四.改进建议:

   题目集6的7-1到7-4这四个正则表达式子的匹配,我认为融合为一个题目较好,设计相应的类。

 

五.总结:

  本次学到了挺多的东西,正则表达式的熟练运用, 有关类的设计实现。与本人上次相比较,发现自己还是有所进步的,圈复杂度等都还行。

  我对封装、继承、多态有了更深的理解,1、封装是隐藏对象的属性和实现细节,对外提供公共的访问方式,以防止数据的随意访问和修改;2、继承是通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类;3、接口的多种不同的实现方式即为多态。

 

posted @ 2021-11-13 15:14  漓尘  阅读(50)  评论(0)    收藏  举报