OO第二次博客作业
一、前言:
第四次题目集
题量:三道题,难度提升,代码量也大幅度上涨。每道题的代码长度平均在250行左右。
知识点:第一题涉及到正则表达式的应用,(进一步了解并使用正则表达式来解决问题)。第二题则是关于聚合的知识点(如果一个类有一个类的实体引用(类中的类),则它称为聚合),第三题是关于继承(子类,父类)类型的题目,也包含了一些面向对象的设计思想。
第五次题目集:
题量:五道题目,难度较第四次题目集而言变化不大。只是单纯多了几道三道简单题。第五题和第四次题目集的第二题是一样的,只是代码的结构不同了,只有第四题有点难度。总体来说,较第四次题目集的难度还有所下降。每道题的代码长度平均在110行左右。
知识点:前三题涉及了选择,冒泡,插入排序和数组的知识点。第四题包含了正则表达式,list, Map 等知识点。第五题继承。
第六次题目集:
题量:六道题,难度也没有太大变化,略微下降。每道题的代码长度平均在100行左右。
知识点:前四题:正则表达式的简单应用。第五题:继承和多态的用法以及Array list的常用方法,泛型的应用和Arrays及Collections的简单应用。
二、设计与分析:
1、 题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较:
题目集四(7-2),题目集五(7-4)

 
 


这两题是两种日期类聚合设计,在这两种代码的Source Monitor的生成报表内容中,可以看出这两种代码的圈复杂度差别不大,但是第四题目集中的方法,关于复杂,差不多每个类之间都有联系,Date Util类与Day类是聚合关系(类Date Util中用到了类Day),类Day与类Month又是聚合关系(类Day中用到了类Month),类Month与类Year也是聚合关系(类Month中用到类Year),如果其中一个环节有问题,就不好改动,会比较繁琐,整得跟个俄罗斯套娃一样。而在第五题目集中的日期类聚合设计中,类Date Util与类Day,类Month,类Year是聚合关系(类Date Util中用到了类Day,类Month,类Year)。但是类Day ,Month ,Year之间不像第四次题目集中那样有着聚合关系,它们是没有联系的。如果要修改的话会更加方便一点。
2、 题目集4(7-3):

 
本题的圈复杂度有点超标,应该是判断数据输入是否正确 的地方用了过多的if-else 语句。
本题的设计思路首先在主函数中先选择四个功能,然后再输入相应的数据,最后输出相应的结果。设计一个无属性的类Shape其中包含一个求图形面积的方法。设计类Circle,类Rectangle,类Ball,类Box都继承类Shape,作为其子类,这些子类分别包含各种图形(圆,矩形,球,立方体)的信息(面积或着体积),如,圆,矩形,球,立方体。主函数通过调用这些子类来输出想要的结果。
技术运用:用到了继承和封装(子类的属性都是私有的)
3、 题目集6(7-5)

 
本题的设计思路和题目集4(7-3)的设计思路是一样的,只不过本题的父类Shape类是抽象类,题目集4中的为具体的类。
题目集6(7-6)

 
本题设计思路:设计Get Area为一个接口,没有属性,其中有一个抽象类的求面积的方法。Circle及Rectangle类分别实现Get Area借口。在Main类的主方法中分别定义一个圆类对象及矩形类对象(其属性值由键盘输入),使用接口的引用分别调用圆类对象及矩形类对象的求面积的方法,直接输出两个图形的面积值。
技术运用:接口,与继承。
1、 正则表达式技术分析总结:
这几次题目集中用到的正则表达式:消除空格:str.replace(“ ”,””);
 
 
 
常用的正则表达式总结:
1、 匹配一个网络地址:[a-zA-Z]+://[\S]+
2、 匹配一个IP地址:(\d+[.]){3}\d+ 或者((([1-9]\d?)|(1\d{2})|(2[0-4]\d)|(25[0-5]))[.]){3}(([1-9]\d?)|(1\d{2})|(2[0-4]\d)|(25[0-5]))
3、 匹配一个邮箱地址:[^\s@]+@[^\s@]+\.[^\s@]+
4、 匹配身份证:\d{15}|(\d{18}|(\d{17}[Xx]))
5、 匹配日期(年-月-日):\d{2}|\d{4})-((0?[1-9])|(1[0-2]))-((0?[1-9])|([12][0-9])|(3[01]))
6、 24小时制时间(小时-分钟-秒):(((0?|1)[0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])
| 
 QQ号码  | 
 [1-9]\d{4,}  | 
| 
 中国大陆固定电话号码  | 
 (\d{3,4}-)?\d{7,8}  | 
| 
 中国大陆手机号码  | 
 1\d{10}  | 
| 
 中国大陆邮政编码  | 
 \d{6}  | 
| 
 汉字  | 
 [\u4e00-\u9fa5]  | 
| 
 中文及全角标点符号  | 
 [\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee]  | 
| 
 不含abc的单词  | 
 (?=\w+)(?!abc)  | 
| 
 正整数  | 
 [1-9]+  | 
| 
 负整数  | 
 -[1-9]+  | 
| 
 非负整数(正整数+0)  | 
 [1-9]+  | 
| 
 非正整数(负整数+0)  | 
 -[1-9]+  | 
| 
 整数+0  | 
 -?[1-9]+  | 
| 
 正浮点数  | 
 \d+.\d+  | 
| 
 负浮点数  | 
 -\d+.\d+  | 
| 
 浮点数  | 
 -?\d+.\d+  | 
5、 题目集5(7-4)中Java集合框架应用的分析总结:
在本题中我用的了Map集合的方法。因为map的键是唯一的,不可重复的。值是可重复的。其用法更加灵活。题目最后是要通过一个关键字去获取该关键字出现的次数,所以觉得用map合适点。
Map概述:
将键映射到值的对象
一个映射不能包含重复的键
每个键最多只能映射到一个值
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效。
Map接口的常用方法:

Map接口方法演示:
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map<String, String> map = new HashMap<String,String>(); //数据采用的哈希表结构
//给map中添加元素
map.put("星期一", "Monday");
map.put("星期日", "Sunday");
System.out.println(map); // {星期日=Sunday, 星期一=Monday}
//当给Map中添加元素,会返回key对应的原来的value值,若key没有对应的值,返回null
System.out.println(map.put("星期一", "Mon")); // Monday
System.out.println(map); // {星期日=Sunday, 星期一=Mon}
//根据指定的key获取对应的value
String en = map.get("星期日");
System.out.println(en); // Sunday
//根据key删除元素,会返回key对应的value值
String value = map.remove("星期日");
System.out.println(value); // Sunday
System.out.println(map); // {星期一=Mon}
}
}
键找值方式:即通过元素中的键,获取键所对应的值
操作步骤与图解:
1.获取Map集合中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键

2.遍历键的Set集合,得到每一个键
3.根据键,获取键所对应的值
Map集合遍历键值对方式:
键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
操作步骤与图解:
1.获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。
2.遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象
3.通过键值对(Entry)对象,获取Entry对象中的键与值。
java笔记--Map的用法_Linias的博客-CSDN博客_java map
java集合框架总结(四)_weixin_34038293的博客-CSDN博客
Java中的Map及其使用_taraex的博客-CSDN博客_java map
三、踩坑心得:
1、 在第四题目集的第三题:
正确结果:
但是我输入相同的数字后得到结果为
最后得到原因:是这个if(radius<0)应该改为<=0;

2、 题目集4第二题:
报错:

原因:没有初始化

3、 题目集4第三题,在做本题中我发现题目的大部分甚至全部测试点的可以从题目中得出,如果某个测试点始终通过不了,那么不妨试试再重新仔细阅读题目,从中分析,最终应该是有所收获的。
四、改进建议:
1、遍历方法1:keyset遍历
Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
int key = iter.next();
String value = map.get(key);
}
//还有一种写法 用for each
for (String key : map.keySet()) {
String value = map.get(key);
}
遍历方法2:
Iterator<Entry<String, String>> iter = map.entrySet().iterator();
Entry<String, String> entry;
while (iter.hasNext()) {
entry = iter.next();
int key = entry.getKey();
String value = entry.getValue();
}
//同样的for each写法
for (Entry<String, String> entry: map.entrySet()) {
int key = entry.getKey();
String value = entry.getValue();
}
另外,在考虑效率方面,for each速度更快一点点,推荐使用for each写法来遍历。
2、警惕自增的陷阱
public static void main(String[] args) {
int count =0;
for(int i=0;i<10;i++){
count=count++;
}
System.out.println("count="+count);
}
可以看到,count最终的输出值是0.
在jv中的执行步骤如下:
1、jv 把count值(0)拷贝到临时变量区。
2、count值加1,此count为1.
3、返回临时变量区的值,此时是0,值没有改变。
4、返回值赋值给count,count重新变为0。
大概类似于如下代码
public static int mockAdd(int count){
//先保存初始值
int temp =count;
//做自增操作
count = count+1;
//返回原始值
return temp;
}
1、 注意边界:
public class Client {
//一个会员拥有产品的最大数量
public final static int LIMIT = 2000;
public static void main(String[] args) {
//会员当前拥有产品数量
int cur = 1000;
Scanner input = new Scanner(System.in);
System.out.print("请输入需要预定的数量:");
while(input.hasNextInt()){
int order = input.nextInt();
//当前拥有的与准备订购的产品数量之
if(order>0 && order+cur<=LIMIT){
System.out.println("你已经成功预定的"+order+"个产品!");
}else{
System.out.println("超过限额,预订失败!");
}
}
}
}
这段代码看似没有问题,但是当输入2147483647时,发现提示订购成功!没错,因为这个到达了int的边界, 2147483647 + 1000 = -xxxxxxxxxx当然小于2000了。!!所以以后我边界一定要注意!!!
五、综合性总结:
继承和多态是java应用非常重要的一个部分,有时候就算你能完整的运行一个程序也不见得这个程序是很好的,因为在大多数时候尤其是以后我们涉及到应用开发时候继承和多态就显得举足轻重。因为有时候你一大篇幅的写下来没有用到继承和多态,别人看你代码时候也很难理解,尤其是也不利于程序的拓展。所以我们要养成一个好的习惯将程序模块化,这就用到了继承和多态了,以前没学习之前我就觉得代码怎么短怎么舒服就怎么写最好,但是并不是,老师常说java编程不仅仅局限于实现更重要的是拓展,这样才会有更好的进补。
                    
                
                
            
        
浙公网安备 33010602011771号