第二次Blog
前言:
题目集04:题量很少,但是不简单,本题目集的知识点还是在正则表达式和类间关系的设计。最难的部分还是正则表达式,水文数据校验及处理这题到最后还是有两个测试点没过,主要是正则表达式不够简洁,导致程序修改起来非常麻烦。正则表达式的知识还是不够精通,需多加巩固。
题目集05:题量不多,老师给我们增加了一些练练手的简单题目,但是重点难点还是集中在两个大题上。知识点主要还是正则表达式和类间关系的设计,类间关系设计是在上一次题目集上的迭代,本次还学习到了有关Java中哈希表的知识,但难点还是在正则表达式上,统计Java程序中关键词的出现次数这道题也是因为正则表达式没有写好导致最后有两个点始终过不了。
题目集06:题量相比而言较多,但是本次题目集非常简单(有手就行)。本次题目集更多的是帮助我们巩固知识点,知识点主要在正则表达式还有继承与多态。本次的正则表达式有关练习都是简单的匹配,大题是有关继承与多态,不是很难,主要在于理解Java中继承与多态的抽象概念还有Arrays及Collections的简单应用。
设计与分析:
①题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较
题目集4(7-2)的类图与题目集5(7-4)的类图比较
题目集4(7-2)

题目集5(7-4)

两次题目集实现的功能都是完全一样的,但是类间的关系不同。从类图中可以看出第一次的类间关系是组合,Day与Month与Year三个类是同生共灭的,三个类的对象会被同时创建。第二次的类间关系是关联的关系,Day与Month与Year三个类是互不相干的,全部在业务类里进行创建对象和操作。
第一次类间的关系是组合,类间耦合度极高。第二次类间关系为关联,耦合度比较低。所以后者可维护性较高。
题目集4(7-2)的类图与题目集5(7-4)的圈复杂度比较
题目集4(7-2)

题目集5(7-4)

从图中不难看出第一次的复杂度比第二次的复杂度更低,虽然第一次的类间关系耦合度高,但是复杂度低。这也导致第二次的题目集总有一个点我过不去,老是运行超时。这两次计算的方法都是进行累加法或者累减法,所以导致圈复杂度有点高,算法上仍需对程序进行改进。
圈复杂度越高,代码就越难复杂难维护。坑就越大。所以如何避免圈复杂度太高是一个很值得探究的问题,这两次的圈复杂度都比10多出一点,主要是if语句判断和for循环太多。由圈复杂度的计算方法可以知道,if语句里的判断条件有几个就加几,所以在构思的时候,可以合并条件表达式,使圈复杂度降低。

后来发现把变量n的属性从int改为long以后就可以通过了。
②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
题目集4(7-3)

题目集6(7-5)

题目集6(7-6)

这三种图形设计都是继承父类或者接口,第一次四个图形均继承自Shape,极大减少了代码量,然后每个类都重载了计算面积的方法,这也利用到了多态的知识。第二次与第一次没有太大区别,在封装性上得到了改进,第三次继承的是接口,这是比较抽象的概念,与抽象父类很相似但又不完全一样。
这三种渐进式图形继承设计从类图中可以看出都使用了继承,三次都具有封装性,也都利用到了多态的知识。封装性,继承和多态是Java面向对象的三大特征,利用好这些特性可以带来很多好处。
封装的好处
便于使用者正确的使用系统,防止错误修改属性。
有助于系统之间的松耦合,提高系统独立性
提高软件的可重用性 降低了构建大型系统的风险
继承的好处:方便修改代码,减少代码量
多态的好处
1.可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程。
2.统一调用标准,一切向父类看齐。
3.提高了程序的扩展性和可维护性。
③对三次题目集中用到的正则表达式技术的分析总结
题目集04
本题目的大题就是主要考察正则表达式的运用 类图如下

圈复杂度:

本次类图主要是根据题目指导书上给的类图构建出来的,相比指导书中的类图有所不同的是我的方法多加了两个,为了更方便判断处理数据。因为在主方法中运用了很多次for语句导致本次圈复杂度有点高。
这次正则表达式确实是令人崩溃,这次的难度和上次求导的题目不相上下。本次题目的难度主要在于如何处理一大串数据,我一开始想分开一行一行处理,但是这样有个测试点我一直过不去,正则表达式的运用其实没有很难,难的是如何保持思路清晰,一行一行来判断处理这些数据。
题目集05
7-4 统计Java程序中关键词的出现次数
作为本次题目集的大题,也是主要考查正则表达式的运用。
本大题并没有类的设计,主要就两个方法,在Main类里就能够实现,太多的类反而不好,容易混乱。
圈复杂度如下:

一开始在构思思路的时候有两个想法,但是很快就否定了想法2,因为正则表达式不能判断是否为单个单词或者是一个句子。
想法1:把所有一长串字符串分割一个个单词
想法2:正则表达式匹配关键字 不合理,无法判断每个单词;

本题使用到的正则表达式其实并不难,都是一些基本功。但是难的地方就是思路上的缺陷,总有一些情况我考虑不到,导致最后有一个点一直过不去。
题目集06
本题集有三个有关正则表达式的小题,都是一些非常简单的题目,主要考察我们的正则表达式基本功。
三个小题分别是qq号校验,验证码校验,学号校验。
其中最复杂的也就是学号校验,但是也没多难,这三小题都是几行代码就完事了。

本次主要考察的就是我们匹配字符的基本功,主要就运用的就是[]这个范围匹配符。
正则表达式常见问题汇总:
1.想匹配同的结果在相同类型的规律下,但是筛选规则只有一处或者两处的差异,这个时候也可以利用.*?的方式来直接替代规则中的差异,也可以使用“|”的方式来进行匹配
2.在匹配想要的数据时,发现.*?的方式得到的结果中有自己不想要的结果,那么就不要使用.*?的方式,自己构建规则,如只需要匹配a-f的字母,那么就可以这样写[a-f],如果还有数字或者特殊符号,那么就再添加[a-f0-9]即可
3.特殊符号,可以单独拿出来讨论,毕竟特殊符号全部拿出来也没有几个,看一下就好了
④题目集5(7-4)中Java集合框架应用的分析总结
本次题目集7-4运用到了HashMap和Set两个包,运用到了Set集合中HashMap的知识,因为在统计关键字出现的次数时,HashMap是一个非常好的选择,刚好HashMap可以有key对应关键词,然后value对应出现次数。
HashMap集合特点:单一,无序
Map.Entry<K,V>
映射项(键-值对)K=key,V=value
HashMap有以下功能和方法
添加功能:V put (K key,V value)
获取功能:V get(Object key), Set< K > keySet(), Collection< V> values(), int size()
判断功能:boolean containsKey(object key),boolean containsValue(Object value),boolean isEmpty()
删除功能:void clear(),V remove(Object key)
遍历功能:Set<Map.Entry<K,V>> entrySet()
部分代码:

本次题目主要运用了添加功能和遍历功能,还有通过key找到value。
采坑心得:
1.计算日期类这道题目中我有两个点总是过不去,样例都是符合的,答案计算没有问题。就是因为测试的数值太大了导致我超时,一开始还以为是PTA平台的问题,结果在提交多次以后还是超时过不去。然后发现把 int的属性改为long莫名其妙就好了,通过了。

2.正则表达式的常见错误
(1)特殊符号要单独拿出来讨论,不然容易匹配出错。
(2)将常规的筛选规则写好后发现只匹配到一部分数据,剩下的数据匹配不到,原因大多是由于换行导致的(在匹配的时候会按行进行匹配的,因为我们写的规则.中默认是没有\n的,所以到换行时就会以为结束。可以使用替代的方式将换行替换掉,也就是将数据全部都放在同一行,或者在规则中添加换行符即可),所以在匹配数据的时候多注意一下换行带来的这个问题。
3.关于split函数的用法
分离字符串的方法中,split方法是常用的。但是在使用过程中会有很多坑。
Java中的 split 函数是用于按指定字符(串)或正则去分割某个字符串,结果以字符串数组形式返回;
例如:
String str="1234@abc";
String[] a = str.split("@");
System.out.println("处理结果: "+a[0]+","+a[1]);
<!--//输出的是: 处理结果: 1234,abc-->
但是在分离时比如分离空格时,第一个分离出的字符可能是空的。例如分离" word word all add"这样一串字符串,字符串数组第一个是"" 第二个是"word"。
改进建议:
这几次正则表达式的大题其实并不会特别的难,但是在这几个大题里我都有一两个测试点没有通过,其实主要原因就是思路构建的不清晰。所以当下次做题目之前,一定要先构建好解题思路,可以想久一点,不着急完成。在完善自己的思路,确保自己的思路没有缺漏。
过这几次题集发现自己写的代码可维护性非常差,当一处思路出现错误时,可能一大半的代码都需要修改,这样写起程序来是非常繁琐的。所以以后写代码时尽量考虑到程序的可维护性,对自己的代码多加改进。
这几次的圈复杂度也都不是很低,基本都是在10左右,在后续优化的过程中尽量把代码的最大圈复杂度降到10以下。
总结:
对于本阶段三次题目集,前两次的题目集都有比较难搞定的大题,最后一次的题目集特别简单。本阶段主要的难点还是在正则表达式的处理上,除此之外主要是在学习面向对象语言的三大特性,封装,继承与多态。这些都是非常抽象的概念,但是在学习并且理解了之后,对我们学习Java和写代码带来了很多好处,让我们对面向对象的编程有了更深的理解。
面向对象有以下特点:
(1)面向对象是一种常见的思想,比较符合人们的思考习惯;
(2)面向对象可以将复杂的业务逻辑简单化,增强代码复用性;
(3)面向对象具有抽象、封装、继承、多态等特性。
在最后的题目集中,虽然简单,但是主要是要让我们理解Java这门面向对象的语言特性,题目集主要让我们在封装性,继承和多态上下功夫,理解了这三大特性后,为我们之后写代码也带来了很多的好处。
圈复杂度分析:
圈复杂度的计算方法如下
圈复杂度(CC) = 判断条件个数 + 1 其中1代表函数本身的复杂度
关键字:if, else if, for, while, &&, ||, case, catch等。
对if,if~else, if~else if ,for, switch , while语句进行简要说明:
If中有几个判断条件算几个,else算一个
else if 有几个判断条件算几个
for 中第二个判断条件有几个算几个
switch 中有几个break算几个
while 中有几个判断算几个
之后函数的圈复杂度是所有的语句判断数加函数本身。
所以在圈复杂度过高的时候,可以从以下几个角度去降低圈复杂度,在以后的设计中尽量不让圈复杂度过高。
(1)可以合并条件表达式,这样可以使条件判断的时候只判断一条,当判断条件过多时,圈复杂度也只+1。
(2)去掉没有必要的else,有些时候可以不用else就尽量不用,因为用了的话圈复杂度就多加1。
(3)switch ,case语句可以用Map替代,case有一个就会让圈复杂度加1,所以有时候可以使用Map替代。

浙公网安备 33010602011771号