ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第二阶段总结性博客

2021-04-28 17:04:44  阅读:120  来源: 互联网

标签:总结性 int 子类 博客 month str year 第二阶段 day


前言:

总的来说,这三次题目难度不是很大,题量中等。

在这几次的题目中,主要学习了正则表达式、组合聚合以及继承和多态,对Java有了更深入的了解和认识。

设计与分析:

 

 ①7-2 日期问题面向对象设计(聚合一)与7-4 日期问题面向对象设计(聚合二)的比较

二者类图:

 

 

 

 

 

 

这两题主要是与聚合有关,在我看来,如果不是为了考察这一知识点,第一题的设计反而会加大编程的难度

 

 

 像这样多层引用在这个程序中出现的许多,常常让我晕头转向,value值是什么?月年or日?在第一次写的时候被这搞得找不着北,第二次重新写时,将各个value值分别命名,最终得到答案。

聚合就像是人与电脑,人可以使用电脑,但是电脑不能使用人,人也可以不使用电脑,但是可能会在某些方面的功能出现欠缺;

而组合可以看做是人和手,手是人的一部分,离开人体后就失去作用,也就是说人消亡后手也就没了。

两个题目在具体功能的实现上也不是很难,求前n天只需用一个循环依次用日期减一就行了,求后n天类似,求两个日期的间隔只要各自求出与1900年1月1日的间隔天数,两个相减然后取绝对值即可得到答案,用这个算法甚至用不到老师设计的比较两个日期大小的方法。

但是这也有一个问题,在聚合二中最后的测试点中有运行超时,我想应该是数字过大所致,然后又加了一个if语句用于判断value是否大于365,如大于则减去365或366,这样可以极大的节省时间

 

 

 总的来说聚合二比聚合一的设计更合理,代码也是更精简,聚合一的类似套娃的设计不仅让我们写代码的人带来了一些困难,也给看代码的人带来了很大的难度,实在不是明智之选。

聚合二部分源码:

    class DateUtil{
        DateUtil(){};
        private Year year=new Year();
        private Month month=new Month();
        private Day day=new Day();
        private int mon_maxnum[]= {0,31,28,31,30,31,31,30,31,30,31,30,31};
        public Day getDay() {
            return day;
        }
        public void setDay(Day day) {
            this.day = day;
        }
        DateUtil(int y,int m,int d){
            day.setDayValue(d);
            month.setMonthValue(m);
            year.setYearValue(y);
        }
        public Year getYear() {
            return year;
        }
        public void setYear(Year year) {
            this.year = year;
        }
        public Month getMonth() {
            return month;
        }
        public void setMonth(Month month) {
            this.month = month;
        }
        public  boolean checkInputValidity(int yearvalue,int month,int dayValue){    //判断输入日期是否合法,返回布尔值
            boolean legal=true,choice=year.isLeapYear();
            if(yearvalue<1820||yearvalue>2020||month<1||month>12||dayValue<1||dayValue>31)
                 legal=false;
            if(month==2)
            {
                if(choice==true)
                    if(dayValue>29)
                        legal=false;
                if(choice==false)
                    if(dayValue>28)
                        legal=false;
            }
            return legal;
        }
        public boolean compareDates(DateUtil date) {
            boolean thisBig=false;
            if(year.getYearValue()>date.year.getYearValue())
                thisBig=true;
            else if(year.getYearValue()>date.year.getYearValue())
                thisBig=false;
            else
            {
                if(month.getMonthValue()>date.month.getMonthValue())
                    thisBig=true;
                else if(month.getMonthValue()<date.month.getMonthValue())
                    thisBig=false;
                else
                {
                    if(day.getDayValue()>date.getDay().getDayValue())
                        thisBig=true;
                    else if(day.getDayValue()<date.getDay().getDayValue())
                        thisBig=false;
                }
            }
            return thisBig;
        }
        public boolean equalTwoDates(DateUtil date) {
            boolean choice=false;
            if(month.getMonthValue()==date.month.getMonthValue())
                    if(day.getDayValue()==date.getDay().getDayValue())
                        choice=true;
            return choice;
        }
        public String showData() {
            String a=year.getYearValue()+"-"+
            month.getMonthValue()+"-"+day.getDayValue();
            return a;
        }
      public DateUtil getNextNDays(int n) {
        boolean choice;
        int nextday=n;
        while(nextday!=0)
        {
        choice=year.isLeapYear();
        boolean choice2=isLeapYear(year.getYearValue()+1);
        if(choice2==true&&nextday>=366)
        {
            nextday=nextday-366;
            year.yearIncrement();
        }
        if(choice2==false&&nextday>=365)
        {
            nextday=nextday-365;
            year.yearIncrement();
        }
        if(choice==true)
            mon_maxnum[2]=29;
        else
            mon_maxnum[2]=28;
        day.dayIncrement();
        if(day.getDayValue()>mon_maxnum[month.getMonthValue()])
        {
            day.setDayValue(day.getDayValue()-mon_maxnum[month.getMonthValue()]);
            if(month.getMonthValue()==12)
            {
                year.yearIncrement();
                month.resetMin();
            }
            else
                month.monthIncrement();
            
        }    

        nextday--;
    }
        return new DateUtil(year.getYearValue(),month.getMonthValue(),day.getDayValue());
    }
        public DateUtil getPreviousNDays(int n) {
            boolean choice;
            int previousday=n;
            while(previousday!=0)
            {
                choice=year.isLeapYear();
                if(choice==true&&previousday>=366)
                {
                    previousday=previousday-366;
                    year.yearReduction();
                }
                if(choice==false&&previousday>=365)
                {
                    previousday=previousday-365;
                    year.yearReduction();
                }
                if(choice==true)
                    mon_maxnum[2]=29;
                else
                    mon_maxnum[2]=28;
                day.dayReduction();
                if(day.getDayValue()==0)
                {
                    
                    if(month.getMonthValue()==1)
                    {
                        year.yearReduction();;
                        month.resetMax();;
                    }
                    else
                        month.monthReduction();;
                    day.setDayValue(mon_maxnum[month.getMonthValue()]);
                }
                previousday--;
            }
            return new DateUtil(year.getYearValue(),month.getMonthValue(),day.getDayValue());
        }
        public int getDaysofDates(DateUtil date) {
            int span,span1,span2;
            span1=numOfDays(year.getYearValue(),month.getMonthValue(),day.getDayValue());
            span2=numOfDays(date.year.getYearValue(),date.month.getMonthValue(),date.getDay().getDayValue());        
            span=span1-span2;
            span=Math.abs(span);
            return span;
            
        }
        //求出year-month-day到0001-1-1的距离天数,返回整型数
        public  int numOfDays(int year,int month ,int day){
            int i,j,cnt=0;
            for(i=1;i<year;i++)
            {
                if(isLeapYear(i)==true)
                    cnt=cnt+366;
                else
                    cnt=cnt+365;
            }
            switch(month) //逆序算法,逐月相加
            {
            case 12:cnt=cnt+30;
            case 11:cnt=cnt+31;
            case 10:cnt=cnt+30;
            case 9:cnt=cnt+31;
            case 8:cnt=cnt+31;
            case 7:cnt=cnt+30;
            case 6:cnt=cnt+31;
            case 5:cnt=cnt+30;
            case 4:cnt=cnt+31;
            case 3:
            {
                if(isLeapYear(year)==true)
                    cnt=cnt+29;
                else
                    cnt=cnt+28;
            }
            case 2:cnt=cnt+31;
            case 1:cnt=cnt+day;
            }
            return cnt;
        }
        public  boolean isLeapYear(int a) {    //判断闰年
            boolean choice;
            if(a%4==0&&a%100!=0||a%400==0)
                choice=true;
            else
                choice=false;
            return choice;
        }
    }

 

 

—————————————————————————————————————————————————————————————————————

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

继承

继承就是保持已有类的特性而构造新类的过程。继承后,子类能够利用父类中定义的变量和方法,就像它们属于子类本身一样。

单继承:在类层次中,子类只继承一个父类的数据结构和方法,一个类只有一个父类

多继承:在类层次中,子类继承了多个父类的数据结构和方法,一个类允许有多个继承

多态

1、使用父类类型的引用只想子类的对象

2、该引用只能调用父类中定义的方法和变量

3、如果子类中重写(覆盖)了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法

4、变量不能被重写(覆盖),重写只针对方法,如果在子类中重写了父类的变量,编译时会报错

转化原则

子类对象可以当作父类对象使用

父类对象不能当作子类对象使用

如果父类引用实际只想的是子类对象,那么该父类引用可以通过强制转化成子类对象使用

接口

接口在JAVA中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

题目分析

在这几题中,都多多少少与继承和多态有关

题目集4中的继承似乎是有一点小儿科了,只要将各个类的继承关系搞清楚,然后创建相应的方法用来计算和返回对应的值即可,没有什么大问题。

而在题目集6中的7-5中还是有那么一些问题的。相较于上面一题而言,这一题多了排序、计算面积总和以及一些输出。在计算面积上没有什么大问题,但是题目要求对这些面积进行排序,于是我就创建了一个

Arraylist来存储每个对象及相应的数据。在存储过程中使用了多态,创建的是shape类型,存储的却是它的子类,这给我带来了极大的便利,不用一个一个进行判断,省去了很多麻烦。

 

然后便是对面积进行排序,以前我只对数字数组进行过排序,并不会Arraylist的排序,经过查阅相关资料后学会了用comparor进行排序

 

只需重写其中的compare方法,然后对相关数据进行处理即可得到排序后的Arraylist。得到排序后的Arraylist所有的问题都解决了。 

 在7-6中用到了接口,实际上我对于接口这一知识点还不是很熟悉,做这道题的时候是照着类图依葫芦画瓢,在eclipse的帮助下完成了这道题

 

 

 不过除去这一点,这题也没有什么难点。

7-5部分代码(多态部分):

        ArrayList<shape> arr=new ArrayList<shape>(a+b+c); 
        for(i=0;i<a;i++)
        {
            Circle circle=new Circle();
            circle.setRadius(in.nextDouble());
//            area=circle.getArea();
//            circle.setArea(area);
            arr.add(circle);
        }
        for(i=0;i<b;i++)
        {
            Rectangle rectangle=new Rectangle();
            rectangle.setLength(in.nextDouble());
            rectangle.setWidth(in.nextDouble());
            arr.add(rectangle);
        }
        for(i=0;i<c;i++)
        {
            Triangle tri=new Triangle();
            tri.setSide1(in.nextDouble());
            tri.setSide2(in.nextDouble());
            tri.setSide3(in.nextDouble());
            arr.add(tri);
        }

 

 

—————————————————————————————————————————————————————————————————————

③正则表达式技术的分析总结

总结:

正则表达式咋一看感觉好像不是很难,只要将一些符号所代表的含义背下来就行了,但是真正到了做题目才发现这个是真的麻烦。

首先是在实际操作中会有很多种情况,比如一个日期,要考虑到每个月份的天数不一样,这一年是不是闰年,要将每一种情况都考虑到,这一点就已经带来了一些困难了;

其次是如何表示这么多种情况,还是以日期为例,如何将每个月份与所对应的天数匹配上,天数是一位数还是两位数,数据的取值区间等等;

最后是用规范的写法将想法用代码写出,比如不知这个格式是否会出现就用“?”,不知出现次数就用"+"等等这些小技巧。

分析:

1、7-1(水文校验)

在这一题中,最大的困难是如何用正则来匹配输入的信息以及分割输入的信息,其次是类的设计。

就结果而言,我是有一些疑问,各个小点都是对的,但是这个点却总是过不了,或许是一个小细节上出了问题,但是经过各种奇奇怪怪输入测试后,结果应该是正确的,可还是过不了这个测试点,这是让我最头疼的。

 不过大体上还是没有问题的,只需用几个正则以及Pattern类就可以解决

这题正则的重点是对数据的分割和匹配。用split将输入的字符串进行分割,然后用matcher方法对其进行合法性进行匹配,还有就是在对相关字符串进行匹配之前要进行空格的删除,否则会影响后面的匹配,这些都有现成的方法可以调用,算法之类的不是很难

 2、7-4 统计Java程序中关键词的出现次数

这一题应该是让我头疼了,在最开始做这题的时候,我的想法是用一个数组存储所有的关键字,再用一个StringBuilder类型的变量存储输入的字符串,然后用两层嵌套循环,循环中用Pattern和matcher和find()方法计算出这个关键字所出现的次数,并且存入另一个数组中

 

 

 

 但是结果却是答案错误,甚至一个点都没有过,然后我看见了题目上还说了不计算字符串和注释中的关键字,发现在这个点上应该是有漏洞的。然后我换了一种算法,先用正则表达式将注释和字符串中的内容替换成空格,

 

 

 

然后用replaceAll方法将各种特殊字符替换成空格,再用split方法分割剩下的这些并存入一个数组中,最后用一个嵌套循环去计算关键字出现的个数。这里有一个小细节就是在创建数组的时候将所有元素初始化为0,这样在最后输出的时候就直接使用一个if判断是否为0,为0不输出就行。

部分代码:

 

public class Main {

    public static void main(String[] args) {
        String keyWord[]=Keywords();
        String a;
        StringBuilder sb = new StringBuilder();
        Scanner in=new Scanner(System.in);
        int i,j,l,cnt=0;
         TreeMap<String,Integer> map=new TreeMap<String, Integer>();
//         Map<String,Integer> map=new HashMap<String, Integer>();
        for(i=0;i<keyWord.length;i++)
            map.put(keyWord[i], 0);
        a=in.nextLine();
        while(!a.equals("exit"))
        {
            if(a.matches("(.*)//(.*)"))
            {
                String[]b=a.split("//");
                sb.append(b[0]+" ");
            }
            else 
                sb.append(a+" ");
            a=in.nextLine();
        }
        String str=sb.toString();
//        String regex="[(\"(.*?)\")|(/\\*(.*?)\\*/)]";
        Pattern p=Pattern.compile("\"(.*?)\"");
        Matcher m=p.matcher(str);
        while(m.find())
          str=str.replace(m.group()," ");
        p=Pattern.compile("/\\*(.*?)\\*/");
        m=p.matcher(str);
        while(m.find())
          str=str.replace(m.group()," ");
        if(str.isEmpty())
        {
            System.out.println("Wrong Format");
            System.exit(0);
        }
        str = str.replace("[", " ");
        str = str.replace("]", " ");
        str = str.replace("-", "a");
        str = str.replace("*", "a");
        str = str.replace("/", "a");
        str = str.replace("+", "a");
        str = str.replace(">", "a");
        str = str.replace("=", "a");
        str = str.replace("!", "a");
        str = str.replace(":", "a");
        str = str.replace("\\", "a");
        str=str.replaceAll("\\p{P}+", " ");
         str= str.replaceAll("[^a-zA-Z]", " ");
         String s1[]=str.split(" +");
         for(i=0;i<keyWord.length;i++)
         {
             for(j=0;j<s1.length;j++)
             {
                 if(s1[j].equals(keyWord[i]))
                 {
                     cnt++;
                 }
             }
             map.put(keyWord[i], cnt);
             cnt=0;
         }
        for(i=0;i<53;i++)
            if(map.get(keyWord[i])!=0)
                System.out.println(map.get(keyWord[i])+"\t"+keyWord[i]);
    }

 

 

 

—————————————————————————————————————————————————————————————————————

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

总结:

数组和集合

数组的长度是固定,改变数组长度的方式是创建新的数组,将旧数组复制到新的数组里.

集合类能存储任意长度的对象,集合的长度可以随着元素的增加而增加,随元素减少而减少

数组和集合的区别

数组既可以存储基本数据类型(存储值),又可以存储引用数据类型(可以不同种对象,存储地址值),数组长度是固定的,不能自动增长

集合只能存储引用数据类型(可以不同种对象,地址值),如果存储基本数据类型时,会自动装箱变成相应的包装类,集合的长度的是可变的,可以根据元素的增加而自动增长

集合是一个接口,它的继承子类和实现类主要有:(图片只绘制了主要框架,具体继承和实现的类没标出)

 

分析:

 

 

 在7-4中我使用的主要是TreeMap类,把关键字当作键,把出现次数当作值,两者组成一对键值对,TreeMap主要是红黑树原理,但是在这里只用到了它的排序,按照键的首字母进行排序,然后进行输出

主要算法在上面已经分析过了,这里不在复述。

 

采坑心得 

 1、运行超时

在提交答案时经常会出现运行超时这一个问题,在我看来主要是算法上有问题,比如一个程序中如果有很多个循环,并且会运行许多次,那么这个程序的效率就会降低,如果相关数值过大的话就会出现运行超时的问题。解决方法就是对算法进行调整,尽量减少循环次数,比如将冒泡排序换成选择排序等等提高代码效率的算法。

 

 

 

2、小测试点无法通过

这个应该是我最头大的一个方面了,大部分通过了测试点而有那么两三个点没过就意味着程序中出现了几个小问题,这种小问题一般都要经过不断的运行测试才能找到,甚至有些时候怎么也找不出来。对于这种情况我有两种应对方法,一是用一种更全面的算法去写这个程序,二是不断的运行测试,用许多奇奇怪怪的输入去测试这个程序,直到找到问题所在。

在题目集4 水文校验中,我就出现了这种情况

 

 

 最开始后面三个点都无法通过,后面我用各种数据尝试,像在数据中加空格、改变数据小数位数、输入英文等,然后发现是正则表达式出了问题,进行相应改变后仍有一个点过不了,不管我怎么去变化就是过不了这个点,最后这题也只能是得到部分分数。

判断数据合法性源码:

            if(!validateMeasureDateTime(a[0]))
                System.out.println("Row:"+this.row+",Column:"+1+"Wrong Format");
            if(!a[1].matches("[1-9][0-9]{0,3}((.)[0-9]{1,3})?"))
                System.out.println("Row:"+this.row+",Column:"+2+"Wrong Format");
            if(!a[2].matches("[1-9][0-9]{0,3}((.)[0-9]{1,3})?"))
                System.out.println("Row:"+this.row+",Column:"+3+"Wrong Format");
            if(!validateGateOpening(a[3]))
            {
                String[]c=a[3].split("/");
                if(!c[0].matches("[1-9](.)\\d{2}"))
                    System.out.println("Row:"+this.row+",Column:"+4+"Wrong Format");
                if(!c[1].matches("[1-9](.)\\d{2}"))
                    System.out.println("Row:"+this.row+",Column:"+5+"Wrong Format");
            }
            if(!a[4].matches("[1-9][0-9]{0,3}((.)[0-9]{1,3})?"))
                System.out.println("Row:"+this.row+",Column:"+6+"Wrong Format");
            System.out.println("Data:"+data);
            legal=false;

 

改进建议 

计算关键字那一题中还有一些问题,比如可以将多个正则表达式概括成一个,这样可以让程序更精简,也是提高了代码的效率。还有就是对Map排序的理解不是很深,只是依葫芦画瓢,对于其深层含义的了解还不是很清晰,仍需加强这方面的学习。

水文校验这题只是按照给出的类图一步一步写,对于其中的联系还不是很清楚,在这方面还需要加强。

总结 

经过这三次题目的训练,学会了正则表达式、继承、多态、集合框架,对于编程能力来说是一次比较大的提升,以前许多想到却无法解决的问题现在也是有了那么一些应对之策。

这几次的题目也不是很难,练练手刚刚好,实验也是刚好能让我理解相关的知识。

但是比较烦恼的就是每次课后有一道题,有题目做我并不排斥,但是每次这个时间都太紧了,有些时候碰到一点事情耽搁的话就无法完成这道题,然后就直接略过这个题目,如果在时间限制上能够更宽裕的话我想会有更好的效果。

标签:总结性,int,子类,博客,month,str,year,第二阶段,day
来源: https://www.cnblogs.com/A-HugeGun/p/14711007.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有