PTA题目集4~6总结
一、前言:总结三次题目集的题量、知识点、难度等情况
(1)题目集4共有三道题 。第一题“水文数据的校验与处理”虽然没有什么新知识,但是它的难度系数是三题中最大的,考察的是对正则表达式的掌握。第二道题“日期问题”接触了新的知识:聚合,照着类图写,很快能上手。第三道题“图像继承”又接触了新的知识:继承,简单的父类子类,入门级的题目。
(2)题目集5共有五道题。该题集题量虽然多,但是偏简单,尤其是前三题,简单基础的正则、数组、排序,同学们做得心情舒畅。但是第四题就让人有点难受了,不仅要求对正则表达式熟练掌握还要完成对map,set等接口的自学,是本次题集最为棘手的一道。第五题乍一看和前一次题集的第二题的输出输入要求一样,但是仔细一看类图是不一样的,而且还多了一个大数据的测试点。
(3)题目集6共有六道题,题目量最多,但难度系数最低,没有很棘手的题目。前四题都是对正则表达式的考察,锻炼加固了我们对正则表达式的运用。第五道题是对继承多态的考察是该题集中最难的一题,但在理解了继承和多态后,就很好上手。第六道题是新知识接口的初步练习,其中的抽象思想很是重要,需要我们自己理解领会。
二、设计与分析:分享其中的几道题目的设计与分析
(1) 题目集4:7-2日期问题面向对象设计(聚合一)
题目集5:7-5日期问题面向对象设计(聚合二)
聚合一:
该题目给出了设计类图,拿到题目,首先大致分析类图,明白各个类之间的关系,是哪个类聚合哪个类,以及聚合的数量;再依照类图写出大体框架,写时明晰聚合关系即可;最后理解各个类的作用,补全框架,完成代码。
聚合在此能更好地对代码进行复用。聚合是关联的一种特殊形式,代表两个对象之间的归属关系。
聚合二:
该题目较聚合一的大致算法是一样的,都同为聚合类型,但聚合的方式有所不同。上一题是“一环扣一环”,Year类扣着Month类,Month类扣着Day类,Day类再扣着DateUtil类,而这一题各个类之间是互不影响的。前一题大多关键方法在Day这个类中,而这一道题的关键方法都在DateUtil类中。
关于聚合一、聚合二题目的小总结:
我个人认为聚合二的代码结构更好,它的耦合性没有聚合一的那么强,代码书写也干净,条理清晰,分工明确。
就从下面一个调用数据的例子来看,就可以发现聚合一代码繁琐的缺陷:
聚合一:
聚合二:
采坑心得:
聚合二该题在pta上的测试点比聚合一多了一个大数据测试,需要把int改为long才可通过测试点。
(2) 题目集4:7-3 图形继承
题目集6:7-5图形继承与多态
题目集6:7-6实现图形接口及多态性
7-3 图形继承:
该题是简单的父类子类的构建,从类图上可以看出类之间继承关系,以Shape为源头,产生两条分支Rectangle和Circle,Rectangle延续出Box,Circle延续出Ball。
由此可以领会到:子类是父类的特殊化,每个子类的实例都是其父类的实例。
7-5图形继承与多态 :
该题相比上一题需要多加注意的是对ArrayList接口的使用,在ArrayList中存入Shape类型对象的实例的引用,而且题目要求必须对list中的图形对象在list中进行排序,而不是对求得的面积进行排序,排序后再次求出各图形的面积并输出。
7-6实现图形接口及多态性:
该题是接口内容中的一道简单的题,接口GetArea实现了对求面积方法的封装,用户不需要选择是圆形的还是长方形的求面积方法,直接通过接口获得面积,使程序简单化,体现“越简单越智能”的思想。
心得:
在此我总结一下这三道题目的注意事项以及所涉及的新知识点:
(1)父类中的私有数据域在该类之外是不可访问的,需通过公共访问、修改器来访问与修改。
(2)要调父类的构造方法就必须使用关键字super,而且这个调用必须是构造方法的第一条语句,不然会引起语法错误。
(3)方法的重写必须与被重写的方法具有一样的签名以及一样或者兼容的返回类型,仅当实例方法可访问时,它才能被重写,静态方法能继承但不能重写。
(4)动态绑定:方法可以在沿着继承链的多个类中实现。JVM决定运行时调用哪个方法。方法可以在父类中定义而在于类中重写。思考下面的代码:
0bject o= new Geometricobject();
System. out . println(o. toString());
这里的 o调用哪个toStringO呢?为了回答这个问题,我们首先介绍两个术语:声明类型和实际类型。一个变量必须被声明为某种类型。变量的这个类型称为它的声明类型。这里o的声明类型是Object。一个引用类型变量可以是 一个null值或者是一个对声明类型实例的引用。实例可以使用声明类型或它的子类型的构造方法创建。变量的实际类型是被变量引用的对象的实际类。这里o的实际类型是CeometricObject,因为o引用使用new GeometricObject() 创建的对象。o调用哪个tostring()方法由o的实际类型决定。这称为动态绑定。
(5)多态,作为面向对象程序设计的三大支柱,可见理解它的重要性。多态可以简单概括为父类型的变量可以引用子类型的对象,使用父类对象的地方都可以使用子类的对象。
(6)抽象类的几点说明:
●抽象方法不能包含在非抽象类中。如果抽象父类的子类不能实现所有的抽象方法,那么子类也必须定义为抽象的。换句话说,在继承自抽象类的非抽象子类中,必须实现所有的抽象方法。还要注意到,抽象方法是非静态的。
●抽象类不能便用new操作符来初始化。但是,仍然可以定义它的构造方法,这个构造方法在它的子类的构造方法中调用。
●包含抽象方法的类必须是抽象的。然而,可以定义一个不包含抽象方法的抽象类。这个抽象类用于作为定义新子类的基类。
●子类可以重写父类的方法并将它定义为抽象的。这很少见,但是它在当父类的方法实现在子类中变得无效时是很有用的。在这种情况下,子类必须定义为抽象的。
●即使子类的父类是具体的,这个子类也可以是抽象的。
●不能使用new操作符从个抽象类创建一 个实例,但是抽象类可以用作一 种数据类型。
(7)接口:接口是一种与类相似的结构,用于为对象定义共同的操作,与抽象类相似,不能使用new操作符创建接口的实例。接口继承和类继承本质上是相同的。
正则表达式技术的分析总结:
常用的知识点总结:
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
? 重复零次或一次
n 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^asdf] 匹配除了asdf这几个字母以外的任意字符
Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
public boolean lookingAt()
尝试将从区域开头开始的输入序列与该模式匹配。
public boolean find()
尝试查找与该模式匹配的输入序列的下一个子序列。
``
public boolean find(int start)
重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
public boolean matches()
尝试将整个区域与模式匹配。
public String replaceAll(String replacement)
替换模式与给定替换字符串相匹配的输入序列的每个子序列。
public String replaceFirst(String replacement)
替换模式与给定替换字符串匹配的输入序列的第一个子序列。
以上是一些最常用的正则表达式的知识点。题目集04(7-1)是水文数据校验及处理,该题让我们使用Java中的字符串处理类以及正则表达式对输入字符串数据进行合法性校验及计算,主要考察的就是我们利用正则表达式去匹配和操作,然后还考察了我们对字符串的处理,题目集05(7-4)统计Java程序中关键词的出现次数,该题考察点和上题考查的内容相似,但是这题考察的非法情况以及注意事项更多一些,这两道题目比较综合,题集06的三道小题就比较简单了,考察的都是一些基础知识点。
下面展示一些水文数据检验的代码:
`//信息格式检验
class CheckData {
private String data;// 当前一条水文信息
private int row;//当前行数
public CheckData() {
}
public CheckData(String data, int row) {
this.data = data;
this.row = row;
}
//把当前的水文数据以"|"分割存入字符串并返回
public String[] getData() {
String[] string = data.split("|");// 分割字符串位字符串数组
return string;
}
public void setData(String data, int row) {
this.data = data;
this.row = row;
}
public boolean validateData() {// 数据合法性校验
String regex="(.*)\\|(.*)\\|(.*)\\|(.*)\\|(.*)";
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(this.data);
boolean flag = true ;
if(matcher.find()){
String measureDateTime = matcher.group(1);//测量时间
String objectWaterLevel = matcher.group(2);//目标水位
String actualWaterLevel = matcher.group(3);//实际水位
String[] gateOpening = matcher.group(4).split("/");//开度:目标开度和实际开度
String waterFlow = matcher.group(5);//流量
if(this.validateMeasureDataTime(measureDateTime.trim()) == false) {
System.out.println("Row:" + this.row + ",Column:1Wrong Format");
flag = false;
}
if (this.validateWaterLevel(objectWaterLevel.trim()) == false) {// 第二列错误
System.out.println("Row:" + this.row + ",Column:2Wrong Format");
flag = false;
}
if (this.validateWaterLevel(actualWaterLevel.trim()) == false) {// 第三列错误
System.out.println("Row:" + this.row + ",Column:3Wrong Format");
flag = false;
}
if (this.validateGateOpening(gateOpening[0].trim()) == false) {// 第四列错误.开度1
System.out.println("Row:" + this.row + ",Column:4Wrong Format");
flag = false;
}
if (this.validateGateOpening(gateOpening[1].trim()) == false) {// 第五列错误.开度2
System.out.println("Row:" + this.row + ",Column:5Wrong Format");
flag = false;
}
if (this.validateWaterLevel(waterFlow.trim()) == false) {// 第五列错误.开度2
System.out.println("Row:" + this.row + ",Column:6Wrong Format");
flag = false;
}
if(flag == false)
System.out.println("Data:" + this.data);
}
else {
System.out.println("Wrong Format\n" + "Data:" + this.data);// 不符合\t情况
flag = false;
}
return flag;
}
// 检验时间
private boolean validateMeasureDataTime(String measureDateTime) {
//时间正则 强大!
String str = "(((([1-9])|([1-9][0-9])|([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-9])(0[48]|[2468][048]|[13579][26]))|(([48]|[2468][048]|[3579][26])00))/2/29)) ((([02468])|(1[02468])|(2[02])):00)";
if (measureDateTime.matches(str))
return true;
else
return false;
}
// 检验水位 和 流量
private boolean validateWaterLevel(String waterLevel) {
String str = "([1-9][0-9]{0,2}(\\.[0-9]{1,3})?)";
if (waterLevel.matches(str))
return true;
else
return false;
}
// 检验开度
public boolean validateGateOpening(String gateOpening) {
String str = "([1-9]\\.[0-9]{2})";
if (gateOpening.matches(str))
return true;
else
return false;
}
public HydrologicalInfo toHydrologicalInfo() {// 该条信息转化为对象
String regex="(.*)\\|(.*)\\|(.*)\\|(.*)\\|(.*)";
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(this.data);
HydrologicalInfo member = new HydrologicalInfo();
if(matcher.find()){
String measureDateTime = matcher.group(1);//测量时间
String objectWaterLevel = matcher.group(2);//目标水位
String actualWaterLevel = matcher.group(3);//实际水位
String[] gateOpening = matcher.group(4).split("/");//开度:目标开度和实际开度
String waterFlow = matcher.group(5);//流量
member.setObjectWaterLever(Double.parseDouble(objectWaterLevel));
member.setActualWaterLever(Double.parseDouble(actualWaterLevel));
member.setObjectGateOpening(Double.parseDouble(gateOpening[0]));
member.setActualGateOpening(Double.parseDouble(gateOpening[1]));
member.setWaterFlow(Double.parseDouble(waterFlow));
String[] time = measureDateTime.split(" ");
String[] time1 = time[0].split("/");
String[] time2 = time[1].split(":");
//年月日 时刻
LocalDateTime Time = LocalDateTime.of(Integer.parseInt(time1[0]), Integer.parseInt(time1[1]),
Integer.parseInt(time1[2]), Integer.parseInt(time2[0]), Integer.parseInt(time2[1]));
member.setMeasureDataTime(Time);
}
return member;
}
}`
题目集5(7-4)中Java集合框架应用的分析总结
`package pta5;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class four {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Scanner in = new Scanner(System.in);
StringBuilder strbuild = new StringBuilder();
String s = "";
int i, j;
int count = 0;
// 一行一行地将数据读取 并存入container
do {
s = in.nextLine();
if (s.equals("exit"))
break;
Pattern p1 = Pattern.compile(".*?(//.*)");
Matcher m1 = p1.matcher(s);
Pattern p2 = Pattern.compile(".*?(/\\*.*?\\*/).*?");
Matcher m2 = p2.matcher(s);
Pattern p3 = Pattern.compile("(\".*?\")");
Matcher m3 = p3.matcher(s);
if (m1.find()) {
s = s.replace(m1.group(1), " ");
strbuild.append(s + " ");
} else if (m2.find()) {
s = s.replace(m2.group(1), " ");
strbuild.append(s + " ");
} else if (m3.find()) {
s = s.replace(m3.group(1), " ");
strbuild.append(s + " ");
} else {
strbuild.append(s + " ");
}
} while (!s.equals("exit"));
// 转化为字符串
String sb = strbuild.toString();
if (sb.isEmpty()) {
System.out.println("Wrong Format");
System.exit(0);
}
sb = sb.replace("=", "h");
sb = sb.replaceAll("[^a-zA-Z]", " ");
// Map接口 关键字:数量
Map<String, Integer> map = new HashMap<String, Integer>();
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", "private", "protected", "public", "return", "short", "static", "strictfp", "super",
"switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile",
"while" };
String[] ss = sb.split(" ");
for (i = 0; i < ss.length; i++) {
for (j = 0; j < key.length; j++) {
if (ss[i].equals(key[j])) {// 找到了关键词
map.put(key[j], 0);// 添加元素
} else {
}
}
}
for (i = 0; i < ss.length; i++) {
for (j = 0; j < key.length; j++) {
if (ss[i].equals(key[j])) {
count = map.get(key[j]);// 根据键获取值
map.put(key[j], count + 1);
} else {
}
}
}
Set set = map.keySet();
Object[] arr = set.toArray();
Arrays.sort(arr);
for(Object k:arr) {
System.out.println(map.get(k)+"\t"+k);
}
}
}`
这道题让我们匹配关键字,用到了正则表达式以及对字符串的操作和处理,题目还要求题目必须使用List、Set或Map中一种或多种,如完全未使用如上接口,是一道综合性题目,
还有两个测试点没有过,不知道是在哪里出了问题。
改进建议:
通过powerdesginer软件可以看出本次程序都描述在主类中,并没有构建出其他的类,改进方面可以在通过构建消除干扰符号类以及检测类两个大类,主类直接为输入字符串new一个对象,只用调用创建类中的功能方法,可以使代码在主类中更为简洁,各类各尽其职,分工明确,代码复用性更高,可读性更强。
第二阶段Blog总结
通过这三次题集的训练,让我对面向对象程序设计有了更深层面的领悟,尤其是对抽象概念的理解,还有就是对正则表达式更熟练地掌握。编码能力和自学能力提高了不少,相信我可以学好这门语言!
原文:https://www.cnblogs.com/weirdTong/p/14726779.html