第二次blog作业

      (1)前言本学期第二阶段的pta作业已经结束,第一阶段的三次pta作业,主要是让我们从C语言过渡到java语言,从面向过程程序设计过渡到面向对线程序设计,在第三次作业我们初步接受了类的定义以及使用,从第四次作业开始,类使用的更加明显,类间关系也逐渐开始使用,比如说聚合,继承。写聚合类,继承类,业务类,一系列的类间关系都有自己不同的关系以及耦合度,第二阶段是学会写这些,我也猜测下一阶段的目标就是改进。第四次作业的7-1水文数据校验及处理 ,7-2日期问题面向对象设计(聚合一),7-3图形继承。第四次作业就是帮助我们更好地了解并使用类及其关系。第五次作业跟第六次作业,老师听取了我们的建议,每次题目集的前几道题也是巩固练习的基础题,后几题就是难题了,每一次我们都是通过题目去学习新东西。比较有特色的几个题就是题目集2的7-4 统计Java程序中关键词的出现次数 ,7-5 日期问题面向对象设计(聚合二),7-4老师让我们使用了map 或list接口去写这道题,很是有挑战性。然后就是题目集6的7-5 图形继承与多态,7-6 实现图形接口及多态性 ,包括做过的两次实验,尤其是第二次第三次实验对农夫过河游戏的持续改进。总体来说,我感觉这三次题目集,对面向对象编程更加一步了解,对模块化以及代码的分析有所进步。

      (2)设计与分析:

7-2日期问题面向对象程序设计(聚合一)

  

 

 

 

 

 

 第四次作业7-2日期问题面向对象设计(聚合一)

1.题目给出了类图,我们只需要将这几个类去实现,并且完成主函数部分的输入,调用,输出即可,题目要求我们利用类的聚合,关于聚合,我理解就是has关系,比如说,学生是个类,里面的属性有着各种信息,然后学生的地址也是个类,地址类中有着省,市,区,街道等一系列的属性。每个学生都有一个地址,所以这里的地址类跟学生类就是一个聚合关系,has的关系,这道题目相当于一个DateUtil有着day,有着month,有着year,然后他们小类中有有着各自的属性,有了这个大体的思路,我们就要进行详细设计了。

2.我们去定义一个dateutil,里面去含有各个的属性year month day,然后去构建属于每个属性的方法,比如说getNextNDays,getPreviousNDays,getDaysofDates等方法。根据图设计,我们还得去定义一下的三个类,并且将其聚合,整体思路就是这样,接下来我们看代码实现。

代码分析:

(由于这几次题目集题目的代码过长,不方便按照思路去写,鄙人将次粘贴进去并且在blog上逐步进行当时的思路分析)

class DateUtil { 
private int year;
private int month;
private int day;    //在这里我们实现聚合关系

public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}

public DateUtil(){//无参

}

public void setYear(int year) {
this.year = year;
}
public int getYear() {
return year;
}
public void setMonth(int month) {
this.month = month;
}
public int getMonth() {
return month;
}
public void setDay(int day) {
this.day = day;
}
public int getDay() {
return day;
}                                       //每个属性都要自己的构造

private int[] maxday = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

private int getDayOfMonth(int year, int month) {    //取出每个月的天数
int days =maxday[month];
if (month == 2 && isLeapYear(year)) {
days = 29;
}
return days;
}

public boolean checkInputValidity(){      // 类中方法的建立判断输入数据是否合法
if((year>2050||year<1900)||(month>12||month<1)||(day<1||day>31)) {
return false;
}
if(month ==4||month==6||month==9||month==11)
if(day>30)
return false;

if(month==2)
{
if(isLeapYear(year)&&day>29)
return false;
if(!isLeapYear(year)&&day>28)
return false;

}
return true;
}

public static boolean isLeapYear(int year) {     //这里是利用布尔值实现闰年的判断
boolean y1 ;
boolean y2 ;
boolean y3 ;
y1=year%4==0;
y2=year%100!=0;
y3=year%400==0;
if((y1&&y2)||y3)
return true;
else
return false;
}

public DateUtil getNextNDays(int n)              //我们进行下一天的计算,计算算法参照前几次题目记得下一天算法

{                                                                         利用年月日的最大阈值来判断变更之后的日期。
int year = this.year;
int month = this.month;
int day = this.day;

for (int i = 0; i < n; i++) {
day++;
if (day > getDayOfMonth(year, month)) {
day = 1;
month++;
if (month > 12) {
month = 1;
year++;
}
}
}
return new DateUtil(year, month, day);
}

 

public DateUtil getPreviousNDays(int n)  //求前n天与后n天的算法基本与nextday相同
{
int year = this.year;
int month = this.month;
int day = this.day;
for (int i = 0; i < n; i++) {
day=day-1;
while (day < 1) {
month=month-1;
if (month < 1) {
month = 12;
year=year-1;
}
day += getDayOfMonth(year, month);
}
}
return new DateUtil(year, month, day);
}

class Day{   //day中有着month
int value;
Month month;
int mon_maxnum[]= {31,28,31,30,31,30,31,31,30,31,30,31};
public Day() {

}
public Day(int yearValue,int monthValue,int dayValue) {
this.month = new Month(yearValue,monthValue);
this.value = dayValue;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Month getMonth() {
return month;
}
public void setMonth(Month value) {
this.month = value;
}

}
class Month{  //month中有着year
int value;
Year year;
public Month() {

}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Year getYear() {
return year;
}
public void setYear(Year year) {
this.year = year;
}

}
class Year{  //定义类year
int value;
public Year() {

}
public Year(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}


}


public boolean compareDates(DateUtil date)//比较当前日期与date的大小(先后)
{
if (this.year > date.year) //年份大一定大
return true;
if (this.year == date.year) {//年相等比较月
if (this.month > date.month)
return true;
if (this.month == date.month) {//年月都相当比较日期

if (this.day >= date.day)
return true;
}
}
return false;
}

public boolean equalTwoDates(DateUtil date)//判断两个日期是否相等
{

if (year == date.year && month == date.month && day == date.day) {              //两个日期相等的充要条件就是年月日都相等
return true;

}
return false;
}

private int[] mon = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};                                                                                                                                                                                                                  //在这里计算两个日期的差值时,首先要进行日期的compare在求日期差数的时候后,由于我想的方法太复杂于是借鉴了一下网上大佬的方法,他这个方法的核心就是在一年中将每个月之间的差值计算出来,然后只需要计算出日期间的差值乘上年数差值,并且去找已表示出来的月份差最近的几天即可,并且在其中根据isleapyear来判断闰年数,用来加上闰年二月的差值。这样一来,避免了比较一次计算一次的循环次数,降低了算法的复杂,并且容易理解

在后来的思考中,我又想到了别的方法,以前做过一道题目就是求输入日期是从公元1年1月1日开始第几天,这样的话我们可以直接写出中量,将输入两个日期都与公元1年1月1日进行差值计算,最后这两个数值进行差的绝对值计算就行,但是需要计算闰年,需要从1一直循环到输入的年数所以运行时间将会延长,并且占用内存较大。


public int getDaysofDates(DateUtil date)//求当前日期与date之间相差的天数
{
DateUtil dateUtil1 = this;
DateUtil dateUtil2 = date;
if (this.compareDates(date)) {//比较谁大谁小
dateUtil1 = date;
dateUtil2 = this;
}

int days;
int leapYearNum = 0;//两日期之间的闰年数
for (int i = dateUtil1.getYear(); i < dateUtil2.getYear(); i++) {
if (isLeapYear(i)) {
leapYearNum++;
}
}

days = 365 * (dateUtil2.getYear() - dateUtil1.getYear()) + leapYearNum;

int b = mon[dateUtil1.getMonth()] + dateUtil1.getDay();
if((dateUtil1.getMonth() > 2) && isLeapYear(dateUtil1.getYear())){
b=b+1;
}
int c = mon[dateUtil2.getMonth()] + dateUtil2.getDay();
if((dateUtil2.getMonth() > 2) && isLeapYear(dateUtil2.getYear())){
c=c+1;
}
int h = 0;
h = days - b +c;
return h;
}

public String showDate()              //最后将所得数据进行题目要求输出
{
return year + "-" + month + "-" + day;
}
}

代码度量复杂度分析:

 

 

 这道题经过思考更改,最大圈复杂度只有11个单位,主要是进行合法度,闰年判断,剩下的代码简洁清晰,并且持续改进,使得复杂度降低不少,在第一次用我的方法计算两个日期间的差值的时候,我当时测的复杂度为61,说明网上大佬的方法更加简洁明了。

调试分析及采坑心得

1.在最开始,理解错了聚合的概念,并且对类图不熟,开始创建了三个类,将每个类的方法单独写在不同的类中,没有理解聚合的has关系,后来经更改,将其聚合在一起。在写next previous 方法是,应该该是大类的方式定义public DateUtil getNextNDays(int n)  与   public DateUtil getPreviousNDays(int n)。

2.其次就是算法改进,在运行超时的情况下只好将算法改进。并且在聚合中,我们判断checkInputValidity()调用到getDayOfMonth()方法会更优。

最后在这里,关于类间的聚合关系,我通过了解之之后,感觉与c语言中的链表特别相似,聚合关系是通过一个个类属性之间,将其连接起来,一个类has另一个,而另一个又has下一个,从而实现高聚合但又低耦合的关系。

 

在这里我要进行一个比较,就是与下一次题目集的相同问题,但是为聚合二的关系

 

 这里的类设计我们这样设计

class DateUtil{

private Year year;

private Month month ;

private Day day ;

}

后面的每个小类中只需要有自己的方法即可不需要再进行像聚合一一样进行“单向传递”

 我们能够看出来这两次的类间关系设计聚合一根聚合二,我认为最大的区别就是以一张图来表示就是

 

 

 

 

 

 如果我们说聚合类是将类聚合是一种串联关系的话,其中如果一步出错后面也会出错,因为是单向不可逆的has关系,但是第聚合二更加可以使得效率提高,代码复用性强。

第一种方法我们要在date里Day day 在Day中 Month month 在Month 中Year year

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

                     

 

 

 1.题目要求输入源码,知道输入exit结束输入,所以们只需要利用while(true)循环来进行输入即可。

 2.大体思路就是将输入的字符利用正则表达式进行符号消除,然后利用空格将字符分割,与库中的关键字进行匹配,记录统计出现次数即可。

 3.按照通常的思路,我们都是创建一个53长度的字符串数组,并且将关键词存入,将输入数据分割并且进行一个一个匹配,但是此题要求使用List、Set或Map中一种或多种接口来实现,所以我觉得就是就是一种创新,根据上网搜了一下用法,在这里我打算用hashmap接口来写集合,map相当于就是一个集合以及跟关键字之间的映射关系,我们可以用此取代传统的字符串数组。

代码分析

public static void main(String[] args) {

Scanner input=new Scanner(System.in);

String a;
StringBuilder ss=new StringBuilder();       //根据网上资料stringbulider用在字符串缓冲区被单个线程使用的时候,stringbuffer适用于多线程的时候,在这里并没有必要。
Map<String, Integer> map=new HashMap<String, Integer>();//然后就是创建hashmap接口
String []key= { "abstract","assert","boolean","break","byte","case","catch",
"char","class","const","continue","default","do","double","else",
"enum","extends","false","final","finally","float",
"for","goto","if","implements","import","instanceof",
"int","interface","long","native","new","null","package",                  //java中的53个关键字进行整合储存
"private","protected","public","return","short","static",
"strictfp","super","switch","synchronized","this","throw",
"throws","transient","true","try","void","volatile","while"

};


while (true) {                    //输入字符数据,并且以exit结束
a=input.nextLine();
if(a.equals("exit"))
break;
if(a.matches("(.*)//(.*)")){//正则表达式判断是否有注释

这个时候可以使用正则表达式 “ (.*)//(.*) ” 来匹配符合双斜杠注释的情况。因为输入的时候是一行一行地输入,所以这一行就是可以这样匹配。通过这样的正则表达式加上字符串分成字符串数组的 split()方法。将双斜杠前后分组,然后我只需要前一组就行了。(后一组是注释的内容不加入StringBuilder 即可)
String b[]=a.split("//");
ss.append(b[0]+" ");//将b[0]+空格存到字符串ss中

}
else {
ss.append(a+" ");          //扩大数组长度,并且将新的字符串附加进去
}
}
int count=0;
String s=ss.toString();

Pattern p=Pattern.compile("\"(.*?)\"");     //以下是利用正则表达式进行特殊符号的消除和替换。
Matcher m=p.matcher(s);
while(m.find()){
s=s.replace(m.group()," ");
p=Pattern.compile("\"(.*?)\"");
m=p.matcher(s);
}
p=Pattern.compile("/\\**(.*?)/");

常见的注释分为 /* */ 和 /** */ 两种形式,这两种形式是可以实现隔行注释(刚刚已经把双斜杠的处理掉了)。在将StringBuilder 转为String类型后整个字符串是很长的一行,那么使用正则表达式“\(.*?)\” 和 “/\\**(.*?)/” 可以匹配到注释的内容使用group方法进行分组,虽然只有一组。然后调用replace()方法将整个组给替换成空格,这样就把注释的内容给删除了。

m=p.matcher(s);
while(m.find()){        在这里我们就需要用到hashmap中的方法,进行寻找关键字的活动。
s=s.replace(m.group()," ");

m=p.matcher(s);
}

// if(s.isEmpty())
// {System.out.println("Wrong Format");
// System.exit(0);
// }
s=s.replace("["," ");
s=s.replace("]"," ");
s=s.replace("-","a");
s=s.replace("*","a");
s=s.replace("/","a");
s=s.replace("+","a");
s=s.replace(">","a");
s=s.replace("=","a");
s=s.replace("!","a");
s=s.replace(":","a");
s=s.replace("\\","a");
s= s.replaceAll("[^a-zA-Z]", " ");     在这里我们讲所有的符号,替换成字母a,然后我们就能再利用正则表达式将其进行替换。

String []b=s.split("[ ' ']");    // 若存在数组的话则进行通过中括号分割,在将其中的东西进行变更
for(int i=0;i<b.length;i++)
{//System.out.println(s1[i]);
for(int j=0;j<key.length;j++)
if(b[i].equals(key[j]))    //将处理好的字符串通过equals进行与字符串数组key中储存的关键字进行比较
{
map.put(key[j], 0);       通过map.put进行获取map集合中的所有键名


}
}
for( int i = 0;i<b.length;i++)
{
for(int j=0;j<key.length;j++)
if(b[i].equals(key[j]))
{ count=map.get(key[j]);
map.put(key[j], count+1);    // 统计数量
}
}
Set set=map.keySet();
Object[] arr=set.toArray();     
Arrays.sort(arr);             //在这里利用arrays.sort进行一下升序排序,利用treemap也是可以进行的。
for(Object k:arr){
System.out.println(map.get(k)+"\t"+k);    //输出格式
}
}
}

但是在这里,没有通过一个点 一个正常测试的点,在那一周由于时间问题没有时间再去将其修改,后来感觉那个点测的就是 java的多种形式。

 

 

 很遗憾无数据输入时本来应该是wrong format 但是当时因为时间问题没有将此测试点通过。

代码度量分析

 

 

 利用sourcemonitor测得最大的圈复杂度值为14,并不是很高,主要是由于必要的循环与判断而产生。 其他的我认为是利用hashmap以及字符串数组进行关键字进行比较时产生的循环。

如果仅用普通的字符串数组去存关键字,不适用集合的话,那么进行一个句子其中关键词查找就要产生53次循环再加上比较,那么代码的复杂度将会大大提高。

调试分析及其采坑心得

在Java中有着许多的可以简化许多功能的方法,比如说平常我们如果要判断输入数据是否正确,我们就得一个个去比较格式,一次次的写循环,很麻烦,我们就可以用正则表达式的方法来代替这个过程进行。

在匹配信息题的话,如果我们需要一个字符库的话,我们就可以进行map或使用list,我们只需要建立一个集合,并且用各种方法去进行匹配,统计,筛出。在这道题中,我认为在编写的过程中,最大的问题就是去了解某个新东西的用法,并且在编写的时候加入自己的思路,就拿问题来看,我一直认为其就是一个库类,我还是在用循环进行一次一次的比较,实际上map.group与map.get就可以实现。并且对于java的输出方式,有着比c语言更多的形式,也是在代码中比较需要注重的细节。

第四次题目集7-3图形继承

 

 

 

 

 

 设计与分析

1.这道题目考察类的继承关系,父类shape具有一个求面积的方法,然后定义的circle类,rectangle类均为此的子类,并且ball是circle的子类,并且重新定义了一个求体积的方法,box是rectangle的子类但是有了一个新的属性高度,所以需要重写求面积的方法

2.继承的时候需要注意以下事项:父类中的私有属性,子类可以继承但是不能访问,父类中的方法被子类继承下来之后需要跟局需求去进行重写override,并且继承父类的子类调用父类的属性以及方法时需要去使用super.。、

代码分析:

首先我们定义的一个shape类并且其中有一个返回0.0的求面积的方法。

class Shape{//shape类
public Shape(){//构造方法并且输出
// System.out.println("Constructing Shape");
}
public double getArea(){//求图形面积的方法
return 0.0;
}
}

然后我们就要定义它的子类circle rectangle

 

class Circle extends Shape{//Circle 继承Shape
private double radius;
public Circle(){//构造方法并且输出
System.out.println("Constructing Circle");
}
Circle(int radius){
this.radius=radius;
}
public double getRadius(){
return radius;
}
public void setRadius(double radius){
this.radius = radius;
}
public double getArea(){
double a = 0;
a = radius * radius * (Math.PI);
return a;
}
}

class Rectangle extends Shape{//rectangle继承shape
private double width;
private double length;
public Rectangle(){//构造方法并且输出
// System.out.println("Constructing Rectangle");
}
Rectangle(int width,int length){
this.width = width;
this.length = length;
}
public double getWidth(){     //get set方法的生成
return width;
}
public void setWidth(double width){
this.width = width;
}
public double getLength(){
return length;
}
public void setLength(double length){
this.length = length;
}
public double getArea(){       //每个继承下来的子类的求面积方法并不相同,所以需要进行覆写。
return width * length;
}
}

接下来就是继承circle rectangle 的子类ball 跟 box了;

class Ball extends Circle{//ball继承circle
public Ball(){
System.out.println("Constructing Ball");
}

public double getArea(){//球的表面积
double b;
b=4 * super.getRadius() * super.getRadius() * Math.PI;
return b;
}
public double getVolume(){//球的体积
double c=0;
c=4.0 / 3.0 * Math.PI * Math.pow(super.getRadius(), 3);     //调用父类的方法时就需要super.父类方法去使用               
return c;
}
}

接下来是定义rectangle的子类box

class Box extends Rectangle{
private double height;        //立方体特有的属性高度  

public Box(){
System.out.println("Constructing Box");
}
public double getHeight(){         //这里的set
return height;
}
public void setHeight(double height){
this.height = height;
}

public double getArea(){//面积
double d;
d=(super.getArea() + height * super.getWidth() + height * super.getLength()) * 2;     熟悉计算表面积公式之后即可完成此计算方法
return d;
}
public double getVolume(){//体积
double e;
e=height * super.getArea();   //在这的就是底面积乘以高的公式
return e;
}
}

 

 

 这个是这道题的类图设计,主要还是一个继承关系的设计有

 然后主函数部分就是根据输入的数字来实现所需的功能,并没有多大的难度代码 

 

代码度量分析     

 

 

 测试之后发现最大圈复杂度为16,还是在预期之内的,但是我认为还会用更好的降低方法因为在进行选择输入的时候我是用的if语句,如果换成switch语句则四个还能再降低。

 

 

 踩坑分析及其调试心得

写起代码来很轻松,但题目中要求输出

    Constructing Shape
    Constructing Rectangle
Constructing Box

这样的一组结果,导致一开始无从下手。但是我想到可以在构造方法中就输出这个结果,Shape类中就输出 

    Constructing Shape

    然后以此类推在每个构造方法中都增加这个输出的语句。

其次就是在子类中调用父类的方法,应用super的方法,这里如果疏忽掉则将显示报错。

第六次题目集7-5 图形继承与多态

 

 

 题目分析及程序设计

1.这道题考察我们的就是类的多态问题,题目只是告诉们要输出面积,但是没有给我们其中详细对象,所以我们要定义抽象类shape ,其中有abstra方法一个是Boolean类型的validate()还有一个double类型的getArea(),由于我们不知道接下来下面中的方法怎么写,所以在这里是不能直接定义返回值。

2.根据此题,我利用idea编译器画出类间关系的类图

 

 

 以此看出其类间关系既是继承,三个形状类都要继承父类的两个方法,只不过在调用时需要去根据需要和要求去进行方法重写。

代码编写

abstract class Shape {
public abstract double getArea();
public abstract boolean validate();
}//抽象类的定义

接下来的定义的类就是shape的子类三个图形,这里重点强调一下其中在子类中调用抽象父类中两个方法的重写

circle中的

public boolean validate()
{
boolean y;
y=radius > 0;
if (y)
return true;
else
return false;
}

以及

public double getArea() {
return Math.PI * radius * radius;
}

rectangle中的

public boolean validate() {
boolean y1 ;
boolean y2;
y1=width <= 0;
y2=length <= 0;

if (y1||y2)
return false;
else
return true;
}

以及

boolean isRectangle() {
return width > 0 && length > 0;
}

Triangle中的

boolean isTriangle() {
boolean y1;
boolean y2;
boolean y3;
y1=a + b <= c;
y2=b + c<= a ;
y3=c + a <= b;
if (y1||y2||y3) {
return false;
} else {
return true;
}

以及

public boolean validate() {
boolean y1;
boolean y2;
boolean y3;
y1=a + b <= c;
y2=b + c<= a ;
y3=c + a <= b;
if (y1||y2||y3) {
return false;
} else {
return true;
}
}

主函数中需要注意的就是排序问题吧我认为,对于一般的循环进行冒泡或 选择排序,那么复杂度会因为循环而提升,在这里我直接用arrays.sort进行排序,使得复杂度降低。

代码度量分析。+

 

 

 在这里我们看到最大圈复杂度为15,也是符合预期结果,我感觉能再降低其单位的方法就是在main方法中了。

 

 

 

 采坑心得及调试分析

        在这道题中我们是利用抽象类来定义子类,在Java语言中,用abstract 关键字来修饰一个类时,这个类叫作抽象类。抽象类是它的所有子类的公共属性的集合,图形多态与继承题目中一直设计到父类中定义的方法在子类中实现或者得到重写,然后再主方法中调用父类创建一个子类,使它多态化。我认为多态的作用可以使得代码更加简洁,在父类中给出方法的签名或者大体细节,然后子类中对父类的方法进行重写。在实际调试中,我们主要还是注重类的设计,理解清多态的意义以及继承关系。

题目集六7-6实现图形接口及多态性

 

 

 

 

 

 代码设计分析:

 这道题要求使用接口,我认为接口是一个保存了方法签名的一个集合。每一个类在使用接口的时候,可以对接口给出的方法进行重写根据题目类图设计可以得到接口  

 

interface GetArea {
public void area();

}这就是接口的设计,类要调用接口的话只需要使用implements去调用,具体在接口中的方法在类中怎么使用,要根据所需及要求重写即可,代码简单,无需详细分析。

代码度量测试

 

 

 由于这道题核心代码只是考察我们接口的定义及使用,其他的地方并没有太大的难度只是一道基础题,所以也是很简单的就通过了而且最大圈复杂度也不是很高。很简单即可通过

Map的初次使用以及正则表达式的使用心得

    在一开始不了解 Map 类 的时候我想使用两个链表,一个保存找出的关键字,另外一个保存它的个数,但是在感觉上实现起来非常复杂直接放弃。然后看了老师在“解题报告”中给的提示,我去看了关于 HushMap 的知识,它可以在存入数据的时候保留一个 “ Key ” 和一个 “ valve ”,也就是说我可以同时将找到的关键字和它出现的次数存入 HushMap 中。

    但 HushMap 在做数据储存时是一个无序的存储,给我在做输出的时候造成了很大的困难。然后找到了 TreeMap 类,它可以将存入的数据做到一个关于“Key” 按字典顺序进行排序。所以我在使用 HushMap 存入数据后然后强制转换为 TreeMap 类,最后输出,但是我觉得这样排序对我说写起来有些困难,所以我就利用了常规排序方法。

通过使用正则表达式在面对复杂的而又具有某种特性的字符串可以大显身手。就比如:在匹配电话号码或者QQ号这种实际案例时可以使用正则表达式“[0-9].*”来匹配含有多个数字的字符串,然后再根据具体的要求写出判断语句进行修改即可。

           正则表达式对于字符串的处理确实方便,但是在进行正则表达式的编写的时候才是最麻烦的。但是如果掌握熟练之后那么会使代码的信息匹配效率大大提高,其简洁性也要比以往的遍历高得多。

    对于Map 和 List 之类的集合,可以说是非常有用。在学C语言的时候链表是一个神奇的数据结构,它存结构体的指针,然后结构体中存数据。

    List就像是一个包装好了的链表,我可以使用各种方法对链表中的数据进行增 删 改 查,而且还能够使用自定义的类型,List 的增加和删除的方法比数组简单的多,但是在进行排序的时候我还是选择了将List转换为数组然后再排序。

改进建议

1.思路不清晰,到时做题总是耗费大量时间,一边写一边想,修改的时候也比较没有头脑的改。在写一道题之前应把题目要求审视清楚并且在纸上画出一幅类图,方便编写也方便修改,并且去熟练使用debug去

自我赶紧查错代码。

2.不会使用新方法,且思想还没有完全向面向对象程序设计过渡过来,一直将一种固定的思路方法延续用,使得写出的程序圈复杂度高,内存大,但是在逐渐的学习中也是学会了很多使得简洁高效的方法比如说

list或map进行集合储存,利用正则表达式匹配信息等。

3.在对难题的思考上不太认真,并且有所退缩,这是我觉得最需要的一件事,改变害怕的一种态度,态度决定一切,说实话,在学c语言的时候我养成了一个坏毛病就是经常copy,但是在学java的时候我一直在改

掉这个坏习惯,除非是到真的自己想不出来的地方以及用法弄不清的时候才会去网上进行借鉴,我希望能够通过下学期的课程,改掉恐惧感,增加兴趣以及能力。

总结

1.关于日期类问题聚合一以及聚合二的总结,

聚合一的缺点:①可视性差,代码写的非常复杂,在阅读起来有很大的困难。②迭代性差。③耦合度过高,基本上所有的类都耦合在了一起,这使得耦合度高违背了“单一职责”的类设计原则。(优点就没找着,可能是我以一种对比的思路进行找,与聚合二的设计差远了)

    聚合二的优点:①可视性强,通过类图可以很清晰的得到各个类之间的关系。②迭代性高,实体类都是独立的,在维护上很方便。③代码的执行效率高,因为它可以像是多线程一样,彼此独立运行然后结果汇总。

    所以可以得出,由于聚合一的设计是一条线性的,节点与节点之间都高度耦合,代码的可复用性差。其实我在做聚合二题目之前试图将聚合一的代码复制过来然后稍微改一下的,(我认为这也算是可复用性差的一种体现),聚合二的设计使得它实体类都是独立互不干扰的,每个类都执行特定的功能和职责,功能已经模块化,可复用性就很强。聚合一的关系类似于一条单向直线,如果想要得到最后一个类,我们必须去走完前三个类并且频繁的访问,四个类之间的耦合度非常的高,不符合我们所说的“高聚合低耦合”的设计概念,关于聚合二,除了以上的优点之外,我还咨询了一下老师,老师说主要是强调这样做的代码可复用性,关于可复用性,目前我的知识浅陋,也不是太深刻了解其含义,网上关于如何衡量可复用性是这么说的:根据复用软件被用到的频繁程度以及实现一个复用软件所需要的代价有多大。一个好的可复用性软件应该具有的特性:简单,与标准兼容,灵活可变,可扩展,参数化,模块化,变化的局部性,稳定以及丰富的文档和帮助。大概就是聚合二的设计使得它实体类都是独立互不干扰的,每个类都执行特定的功能和职责,功能已经模块化,可复用性就很强。一个类承担的职责越多,它被复用的可能性越小,如果一个类中承担的职责过多,这几个类耦合在一起,若一个变化时,可能就会影其他职责的运作。

2.关于这次作业的总体总结

     上个月的pta作业我认为就是帮助我们对语法的一个过渡,这个月的pta题目应该就是对面向对象程序设计开始进行真正的学习,通过类间关系的训练熟悉,以及正则表达式,map接口等工具的使用,使得我们的编写效率提升很多,真正的开始学习程序设计,在面向对象程序设计中,对象即是最重要的,我们如何面向对象编程,既是对类的使用,我认为这几次题目集最有挑战性的题目就是水文类以及利用map或list接口进行代码关键字匹配排序,其他的题目以及两次实验都是让我们熟悉类中对象的调用,类间关系的设计。我认为,下学期共四个月的学习,我们下个月的学习将会是java中改进代码以及迭代等高级方式的输入输出及信息处理,最后一个月既是综合应用,考虑多方面因素自己设计,难度会逐步增加,压力也逐步增加,我希望能够将压力化作动力,好好学习,为以后的学习以及工作打好基础。  

 

 

 

 

 

 

 

 

 

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             

  

 

posted @ 2021-04-26 21:04  。彭于晏。  阅读(118)  评论(0)    收藏  举报