java第二次博客

  •  前言

         1. 习题集四前言

         本次习题集,共分为三道题,第一道题的难度较大,水文数据的处理与检验,考察了正则表达式以及对正则表达式的处理,是本次习题集较难的一道题目,第二题考察了用类的聚合关系,求下n天,前n天,以及两个时间节点的相差天数,第三题考察了,采用类的继承来解决图形的面积问题,以及子类对于父类的方法重写,相对于第一道题目,处理日期的题和求面积的题相对简单,第一道的水文数据的处理与检验,是本次习题集较难的一道题目,不仅考查了我们对于正则表达式的熟练程度,而且也考察了我们对于字符串的处理,怎样划分字符串等等。

         2. 习题集五前言

         习题集五的难度相对于习题集四的难度有所下降,本次题目集共分为五道题,第一道题为寻找出最长的单词,考察了我们对于字符串数组,以及字符串.length()方法的用法,相对简单,第二题两个升序数组合并为一个新的升序数组,考察了我们对于排序方法的掌握程度,难度为中等,第三题考察了三种排序方式,选择排序,插入排序,冒泡排序,选择排序以及冒泡排序在C语言中我们已经掌握,插入排序上网查询后也掌握了,这道题的难度也为中等,第四题统计Java中关键词的出现次数,考察了我们对于字符串处理的方法,又让我们掌握了一种新的接口方法,关于Java中map的使用,这道题是本次习题集中较难的一道题目,第五题,是对于习题集四的改进,采用聚合类的设计处理日期问题,相对于习题集四的日期处理,这道题目类与类之间的调用关系发生了改变,难度相对于习题集四有所提高。

         3.习题集六前言

         习题集六,有了一些提升我们正则表达式的小题,难度较为简单,第一题QQ号检验以及第三题验证码检验和第四题的学号检验,只需要我们写出对应的正则表达式,即可解出这三道题目,这三道关于正则表达式的题目相对于前两次的正则表达式的难度有所下降,难度为简单,第二题字符串排序,考察了这个题考察了我们,字符串中的字符转化为ASCII码进行升序排序,首先我们需要掌握字符转化为ASCII码值的方法,在运用学到的排序方式进行排序即可。第五题,图形的多态与继承,是本次题目集中最难的一道题目,考察了类的继承,多态性以及使用方法,第六题考察了抽象接口,以及接口的实现,难度为中等,主要是我们对于接口的理解和实现。

 

三次题目集,的难度较为中等,但考察的知识多样,两次聚合类的设计,让我对类的聚合关系理解更加深刻,还有类的继承和多态,本次考察主要向我们渗透了一些关于Java的设计原则,让我们能更加深刻的思考类与类之间的关系,从而深入的了解面向对象的设计原则,这些都是这三次习题集考察的亮点

三次习题集的得分情况:

习题集四:84分

习题集五:86分

习题集六:100分

  •   设计与分析

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

首先从类图来分析:

第一个为习题集四第三题类图,第二个为习题集五第五题类图

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

从类图的复杂度我们可以看出,习题集四第三题的类与类之间的耦合性较大,依赖性也较大,老师上课说过类的耦合性不能过高,我们很难去实现类的单一职责性,如果有一个类的设计出现了问题,那么整个程序的功能都无法正常运行,这与设计原则中的单一职责性相违背,反观习题集五的日期类的耦合性,相对于习题集四的类的耦合性有所降低,使类与类之间的联系不那么紧密,从而使类的功能更加的具有单一性,所以就类图来看,习题集五的日期类明显要优于习题集四的日期类的设计。

其次从圈复杂度来分析:

 主要从DateUtil类的圈复杂度来分析(因为求下n天,以及前n天,和两个日期间的相差天数都是在这个类中实现)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

从圈复杂度我们可以看到,题目集四的日期DateUtil类的圈复杂度是高于习题集五DateUtil的圈复杂度,两者的平均复杂度基本没有差异,可是最大的圈复杂度一个为21,一个为16,圈复杂度应该越低越好

  • V(G) ∈ [ 0 , 10 ]:代码质量不错;
  • V(G) ∈ [ 11 , 15 ]:可能存在需要拆分的代码,应当尽可能想措施重构;
  • V(G)∈ [ 16 , ∞ ):必须进行重构;

从这几点分析来看,习题集五的类的圈复杂度虽然低于习题集四日期类的圈复杂度,但两者的圈复杂度都是大于16的,已经是需要进行重构的了,但是这是我们平时解题,以解决问题为主来设计代码,所以在开始设计的时候,我并没有注意圈复杂度,或者怎样减少圈复杂度

圈复杂度就是统计一个函数有多少个分支(if,while,for等)每增加一个分支,复杂度加1。

老师说过用switch语句来代替if语句可以有效的减少圈复杂度

 

下面是我从网上寻找的降低圈复杂度的方法,在今后的学习或者在解决PTA题目时会学着慢慢的渗透和尝试降低圈复杂度的方法。

Composing Methods(重新组织你的函数)

Extract Method(提炼函数)

Substitute Algorithm(替换你的算法)

•Simplifying Conditional Expressions(简化条件表达式)

Decompose Conditional(分解条件式)

Consolidate Conditional Expression(合并条件式)

Consolidate Duplicate Conditional Fragments(合并重复的条件片断)

Remove Control Flag(移除控制标记)

•Making Method Calls Simpler(简化函数调用)

Separate Query from Modifier(将查询函数和修改函数分离)

Parameterize Method(令函数携带参数)

Replace Parameter with Explicit Methods(以明确函数取代参数)

 

总结:总的来说习题集五的日期类要优于习题集四的日期类,不论是从圈复杂度还是从类图中类与类之间的关系都可以看出,习题集五的日期类设计要优于习题集四的日期类设计,习题集五的日期类设计之间的耦合性更低,类与类之间的关系也较少,符合我们最近所学习的面向对象设计原则,习题五类的设计职责也比较单一,符合单一职责性。

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

首先从类图来分析:

左边是习题集四类的继承求面积问题,右边是习题集六类的继承与多态求面积问题

下面是抽象接口求面积问题:

 

首先分析设计思路:

习题集四:首先设计一个Shape父类,里面定义一个getArea的方法,接下来两个子类Circle和Rectangle继承于Shape类,在两个子类里面需要对getArea方法进行重写,然后Box继承于Rectangle,Ball继承于Circle,从而达到了求立体图形的表面积和体积。

习题集六:继承与多态解决:首先定义一个父类,Shape为抽象类,里面有两个抽象方法,一是得到面积getArea方法以及合法值检验Validate方法,三个子类Circle、Rectangle 及 Triangle继承于抽象父类Shape,在子类中实现两个抽象方法的实体化,从而得到了图形的体积与表面积

习题集六:抽象接口实现图形的面积求法:首先定义一个getArea的抽象接口,里面有抽象方法getArea,再在Rectangle和Circle两个类中,实现对于抽象类以及抽象方法的实体化,从而实现了求图形面积。

然后分析技术运用:

习题集四,采用继承的方法来求图形的面积和体积:

首先谈谈继承的好处:

子类拥有父类非 private 的属性、方法。

子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

子类可以用自己的方式实现父类的方法。

再总结以下继承的坏处:

1、破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性(增加了父类与子类的耦合性)

2、支持扩展,但是往往以增强系统结构的复杂度为代价
3、不支持动态继承。在运行时,子类无法选择不同的父类

4、子类不能改变父类的接口

习题集六采用继承与多态来解决图形面积问题:

首先谈谈多态的特性:所谓的“多态”,简单的理解就是对象在不同情况下的不同表现,具体体现在定义和功能两个方 面,简单的总结一下,多态可以用“三个定义和两个方法”来总结。三个定义分别是父类定义子类构 建、接口定义实现类构建和抽象类定义实体类构建,而两个方法分别是方法重载和方法重写。采用的是抽象类定义、实体类构建的方式。即 Shape 为抽象类,Circle、Rectangle 及 Triangle 为实体类。

 1.提高了代码的维护性(继承保证) 2.提高了代码的扩展性(由多态保证)

多态更好的实现了程序的封装性

习题集六,第六题采用抽象接口来解决图形的面积问题:

定义一个接口,再定义抽象方法,再继承进行方法的实体化,有利于编写的代码更好的延展性,有利于我们对于代码进行更好的维护,保证代码的安全和严密

总结:不论是继承还是多态,或是抽象接口都是为了提高我们的代码的封装性,怎样减少子类与父类之间的耦合性,以及怎样提高我们代码的封装性,都是我们在今后的学习中更多的需要重视的地方,我们所学到的方法更多的是,让我们有更好的编程思维。为了更好的提高代码的复杂性。

 

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

 1.掌握对于字符串处理的方式

1 StringBuilder hydrologicData = new StringBuilder();

通过,这个类将字符串进行添加划分,达到处理字符串的目的,具体的方法为:str.append();这个具体的方法在,习题集四处理水文数据中用到了。

2.划分字符串的方法

1  String[] a = data.split("\n");

通过这一方法,我们可以将我们要处理的水文数据转化为字符串数组,达到分组处理的目的;

3.pattern和matcher的匹配合法字符串的技术

 Pattern sort = Pattern.compile("((([1-9]{1}|[1-9][0-9]{1}|[1-9][0-9]{2}|[1-9][0-9]{3})/((([13578]|1[02])/([1-9]|[12][0-9]|3[01]))|(([469]|11)/([1-9]|[12][0-9]|30))|(2/([1-9]|[1][0-9]|2[0-8]))))|((([1-9]{0,1}[0-9]{0,1})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))/2/29)) ([02468]|1[02468]|2[02]):00");
            if( sort.matcher(str).matches())
                return true;
            return false;

通过这一方法我们可以匹配到,合法的水文数据,从而进行判断,我们输入的水文数据的合法性,主要用于我们输入正确的正则表达式,进行正确的校验。

4.将字符串转化为整形数,用于,水文数据的运算;

1         int year =Integer.valueOf(yearAndMonthAndDay[0]);
2         int month =Integer.valueOf(yearAndMonthAndDay[1]);
3         int day =Integer.valueOf(yearAndMonthAndDay[2]);
4         int minute =Integer.valueOf(minuteAndsecond[0]);
5         int second =Integer.valueOf(minuteAndsecond[1]);

Integer. valueOf()可以将基本类型int转换为包装类型Integer,将字符串型转化为整形,方便了我们的运算。

5.替换字符串中的内容

1  cs= cs.replaceAll("[^a-zA-Z]", " ");

运用这个方法可以将字符串中,我们不需要的内容,或者是无用的内容,替换为,我们想要使其成为的内容,从而更好的处理字符串。

 

6.习题集六的一些简单的正则表达式设计

1 String rule = "[1-9]?[1-9]?[1-9]?[A-Za-z]";
2 String rule = "[1-9][0-9]{4,14}";

总结:通过三次习题集的正则表达式练习题,使我们对于正则表达式有了更深入的了解,提高了我们对于字符串处理的能力,正则表达式,就是们设定的一种关于字数串是否合理的一些表达式,用他们就可以检验出,我们输入的数据是不是合法,如果合法再进行进一步的处理,另外在这次题目中也渗透了一些关于字符串处理的方法,比如字符串数组的划分等等,都提高了我对于字符串的处理能力。

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

1.本次题目涉及到的集合框架

1 Map<String, Integer> map1=new HashMap<String, Integer>();

该接口中所包含有三个方法

get方法:获取指定键(key)所对应的值(value);

put方法:将指定的键与值对应起来,并添加到集合中;

remove方法:根据指定的键(key)删除元素,返回被删除元素的值(value)

1  Set set=map1.keySet();

获取所有键值对对象的集合

set 遍历输出想要的键与对应的值

1  Arrays.sort(String);
2          for(Object num:String){
3              System.out.println(map1.get(num)+"\t"+num);
4          }

2.使用集合框架的好处

 1.我认为集合框架,很方便的帮助我处理了数据,在编程时提供了很多的便利,可以对我们进行储存的数据,进行很好的查阅和修改,方便了我们对数据的处理。

 2.集合框架中的一些遍历的方法,都极大的减少了我们代码的圈复杂度,使我们的代码看上去简洁的同时,又实现了功能.

 3.集合框架真的很方便。

 4.集合框架相对于数组,我认为,数组只要确定了,他的长度也确定了,二而集合框架是一个动态的长度,根据我们的需要往里面添加数据。

 5.我认为集合框架一定程度上也简化了我们的代码,不论是遍历,还是插入等,比起我们用数组for循环遍历好了许多。

 

总结:我认为集合框架带给了我们许多好处,在今后的学习中,我仍然需要去掌握关于Java 学习框架的使用,这些接口都是C语言所没有的,也是面向对象带给我们的好处,这些方法都优于我们平时所用的数组,遍历也优于我们平时的for循环遍历,关于Java一些较好且较为便利的功能仍然需要我去进一步的学习。

  • 踩坑心得

①不同的圈复杂度对应不同的代码质量,当代码的圈复杂度高于20,需要我们进行立即重构,10与20之间的需要我们进行优化,代码的圈复杂度是衡量代码的一个很好的标准,小于10的圈复杂度为优秀的代码,达到了标准。

②类与类之间会有相互调用的现象,这也增加了类与类之间的耦合性,怎样减少代码的类与类之间的关系及其耦合性,是我今后要学习的主要的进取方向,在减少类与类的耦合性的同时,也达到了我们设计代码的目的,也满足了程序的设计原则。

③在设计类的时候,圈复杂度还是较大,怎样减少圈复杂度也是我今后要学习的一个地方。

④类与类之关系,以及怎样更好的减少类与类之间的关系,在设计代码时,我设计的两个类总是有很多的关联,子类继承父类的功能,这些关系我在解题时依然不清楚。

  • 改进建议

①减少圈复杂度,在网上查找的减少圈复杂度的方法,都可以减少我的代码圈复杂度,比如用switch代替if else ,减少判断。

②代码的设计应尽可能的具有单一职责性,一个功能一个类,功能越复杂的类的代码其复用性越差,越不利与我们对于代码的复用。

③减少代码与代码的耦合性,一个类应该对自己需要耦合或者调用的类知道的越少越好,遵循迪米特原则

④设计子类和父类,对于需要不断进行更改和使用的方法应该进行抽象化,用子类去继承他们,减少我们对于代码的修改,遵循开闭原则。

⑤在一些代码的关键节点,我应该加上一些注释,方便之后的查阅和修改。

⑥不断优化实现功能的代码算法,减少代码的圈复杂度

  • 总结

①通过三次的习题集,尤其是题目集4(7-2)、题目集5(7-4)这两个题在关于类设计的时候,设计到的程序设计原则,实现同样的功能,类的设计却有好几种可能,怎样使类的设计更加的合理,能大大的提高我们代码的质量。

②圈复杂度降低的方法有很多,在题目集4(7-2)DateUtil,这个类的设计时里面的方法,求下n天,求前n天,求两个日期的天数差,在这里就体现出了,圈复杂度的方法,第一次设计的时候圈复杂度为21,第二次我将if-else 改换掉成switch,使得代码的圈复杂度降到了16,所以还是有方法来降低圈复杂的,在今后的设计中,我要不断的进行实践和总结。

③一个类应该对自己需要耦合或者调用的类知道的越少越好,遵循迪米特原则,在今后的设计中应尽可能的减少代码之间的联系,实现同样的功能,类的功能也应该单一,类的行驶的功能越多,这个类的复用性越差。

④集合框架的使用是比C语言的数组好很多,有些接口很方便,能很好的帮我们处理数据,减少我们处理数据花费的时间,在今后的设计中,自己要学着使用这些方便的集合框架的接口,从而使我们的代码更加的简洁,且实现功能。

⑤在一些算法设计时,我应该加适当的注释,方便我的观看和修改,要不然很容易出现第二次看时看不懂的现象,也能方便我的使用,在一些代码的关键节点我应该加上一些注释,方便之后的查阅和修改。

⑥设计的代码应该符合面向对象的设计原则,学会使用abstract抽象方法和抽象类,把那些一直使用的方法,和可能改变的类,进行抽象,能极大的提高我们代码的复用性,同时也提高了我们代码的拓展性。

⑦这三次的习题集,又进一步的提升了我的编程能力,初步形成了面向对象设计的思想,以及类与类之间的关系都得到了一定程度的掌握,这三次习题集的有一定的收获。

posted @ 2021-05-01 15:23  一叶之秋十三先生  阅读(249)  评论(0)    收藏  举报