题目集4-6总结
一.前言:总结三次题目集的知识点、题量、难度等情况
题目集4中涉及了了继承的使用,子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。构造方法的使用,当类实例化一个对象时会自动调用构造方法。getter和setter方法的自动生成。
还包含了如何如何求日期下n天,求前n天,求两个日期相差天数。
题目集5主要涉及了找出长度最长的单词,合并两个升序排序的整型数组为一个新的升序整型数组并输出,分别使用插入排序、选择排序及冒泡排序三种算法对整型数据进行排序(升序)
题目集6主要训练了正则表达式的使用,还有对接口的使用。本次题目集训练题量较大,但是题目难度比之前低,难度适中,我感觉更好的锻炼了我的编程能力。
二.设计与分析
1.题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较
答:题目集5的聚合设计更优,减少了类之间的耦合,直接让Dateutil类和其他类实现聚合,维护了代码的可重用性。
题目:
求下n天
求前n天
求两个日期相差的天数


import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int type = input.nextInt();
if(type == 1) {
int year = input.nextInt();
int month = input.nextInt();
int day = input.nextInt();
int n = input.nextInt();
DateUtil dateUtil = new DateUtil(year,month,day);
if(!dateUtil.validate()) {
System.out.println("Wrong Format");
return ;
}
while(n > 0) {
dateUtil.nextDate();
n --;
}
dateUtil.display();
} else if (type == 2) {
int year = input.nextInt();
int month = input.nextInt();
int day = input.nextInt();
int n = input.nextInt();
DateUtil dateUtil = new DateUtil(year,month,day);
if(!dateUtil.validate()) {
System.out.println("Wrong Format");
return ;
}
while(n > 0) {
dateUtil.preDate();
n --;
}
dateUtil.display();
} else if (type == 3) {
int year1 = input.nextInt();
int month1 = input.nextInt();
int day1 = input.nextInt();
int year2 = input.nextInt();
int month2 = input.nextInt();
int day2 = input.nextInt();
DateUtil dateUtil1 = new DateUtil(year1,month1,day1);
DateUtil dateUtil2 = new DateUtil(year2,month2,day2);
if(!dateUtil1.validate() || !dateUtil2.validate()) {
System.out.println("Wrong Format");
return ;
}
long x = year1*10000 + month1*100 + day1*1;
long y = year2*10000 + month2*100 + day2*1;
if(x == y) {
System.out.println(0);
} else if(x > y) {
long count = 0;
while(dateUtil1.getYear() != dateUtil2.getYear() || dateUtil1.getMonth() != dateUtil2.getMonth() || dateUtil1.getDay() != dateUtil2.getDay()) {
count++;
dateUtil1.preDate();
}
System.out.println(count);
} else if(x < y) {
long count = 0;
while(dateUtil1.getYear() != dateUtil2.getYear() || dateUtil1.getMonth() != dateUtil2.getMonth() || dateUtil1.getDay() != dateUtil2.getDay()) {
count++;
dateUtil1.nextDate();
}
System.out.println(count);
}
} else {
System.out.println("Wrong Format");
return ;
}
}
}
class DateUtil {
private int year;
private int month;
private int day;
public int days[] = new int[13];
public DateUtil() {
}
public DateUtil(int year, int month,int day) {
this.day = day;
this.month = month;
this.year = year;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public void nextDate() {
days[1]=31;days[2]=28;days[3]=31;days[4]=30;days[5]=31;days[6]=30;
days[7]=31;days[8]=31;days[9]=30;days[10]=31;days[11]=30;days[12]=31;
if(judgeLeap(year)) {
days[2] = 29;
} else {
days[2] = 28;
}
day++;
if(day > days[month]) {
day = 1;
month++;
if(month > 12) {
month = 1;
year++;
}
}
}
public void preDate() {
days[1]=31;days[2]=28;days[3]=31;days[4]=30;days[5]=31;days[6]=30;
days[7]=31;days[8]=31;days[9]=30;days[10]=31;days[11]=30;days[12]=31;
if(judgeLeap(year)) {
days[2] = 29;
} else {
days[2] = 28;
}
day --;
if(day == 0) {
month --;
if(month == 0) {
year --;
month = 12;
}
day = days[month];
}
}
public boolean judgeLeap(int year) {
if( (year%4 == 0 && year%100 != 0) || year%400 == 0 )
return true;
else
return false;
}
public boolean validate() {
days[1]=31;days[2]=28;days[3]=31;days[4]=30;days[5]=31;days[6]=30;
days[7]=31;days[8]=31;days[9]=30;days[10]=31;days[11]=30;days[12]=31;
if(year < 1900 || year > 2050 || month < 1 || month > 12 || day < 1 || day > 31) {
return false;
}
if(judgeLeap(year)) {
days[2] = 29;
} else {
days[2] = 28;
}
if(day > days[month]) {
return false;
}
return true;
}
public void display() {
System.out.println(year + "-" + month + "-" + day);
return ;
}
}
2.题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
(1)题目集4(7-3)
设计:圆类Circle和Rectangle类继承了shape类的方法和属性;然后球类Ball和Box类又分别继承了Circile类和Rectangle类的方法和属性,
使得代码更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码) 。
题目:
编写程序,实现图形类的继承,并定义相应类对象并进行测试。
- 类Shape,无属性,有一个返回0.0的求图形面积的公有方法
public double getArea();//求图形面积 - 类Circle,继承自Shape,有一个私有实型的属性radius(半径),重写父类继承来的求面积方法,求圆的面积
- 类Rectangle,继承自Shape,有两个私有实型属性width和length,重写父类继承来的求面积方法,求矩形的面积
- 类Ball,继承自Circle,其属性从父类继承,重写父类求面积方法,求球表面积,此外,定义一求球体积的方法
public double getVolume();//求球体积 - 类Box,继承自Rectangle,除从父类继承的属性外,再定义一个属性height,重写父类继承来的求面积方法,求立方体表面积,此外,定义一求立方体体积的方法
public double getVolume();//求立方体体积 - 注意:
- 每个类均有构造方法,且构造方法内必须输出如下内容:
Constructing 类名 - 每个类属性均为私有,且必须有getter和setter方法(可用Eclipse自动生成)
- 输出的数值均保留两位小数

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input= new Scanner(System.in);
while (input.hasNext()) {
int type=input.nextInt();
if(type==1){
double radius=input.nextDouble();
if(radius<=0.0){
System.out.println("Wrong Format");
}
else {
Circle circle = new Circle(radius);
System.out.println("Circle's area:" + String.format("%.2f",circle.getArea()));
// System.out.printf("Circle's area:%.2f\n",circle.getArea());
}
}
else if(type==2){
double width=input.nextDouble();
double length=input.nextDouble();
if(width<=0.0||length<=0.0){
System.out.println("Wrong Format");
}
else {
Rectangle rectangle = new Rectangle(width,length);
System.out.println("Rectangle's area:" + String.format("%.2f",rectangle.getArea()));
// System.out.printf("Rectangle's area:%.2f\n", rectangle.getArea());
}
}
else if(type==3){
double radius=input.nextDouble();
if(radius<=0.0){
System.out.println("Wrong Format");
}
else {
Ball ball=new Ball();
ball.setRadius(radius);
System.out.println("Ball's surface area:" + String.format("%.2f",ball.getArea()));
// System.out.printf("Ball's surface area:%.2f\n",ball.getArea());
System.out.println("Ball's volume:" + String.format("%.2f",ball.getVolume()));
// System.out.printf("Ball's volume:%.2f\n",ball.getVolume());
}
}
else if (type==4){
double width=input.nextDouble();
double length=input.nextDouble();
double height=input.nextDouble();
if(width<=0.0||length<=0.0||height<=0.0){
System.out.println("Wrong Format");
}
else {
Box box = new Box();
box.setHeight(height);
box.setLength(length);
box.setWidth(width);
System.out.println("Box's surface area:" + String.format("%.2f",box.getArea()));
// System.out.printf("Box's surface area:%.2f\n", box.getArea());
System.out.println("Box's volume:" + String.format("%.2f",box.getVolume()));
// System.out.printf("Box's volume:%.2f\n", box.getVolume());
}
}
else {
// System.out.printf("Wrong Format\n");
System.out.println("Wrong Format");
}
}
}
}
class Ball extends Circle {
private double radius;
public Ball(){
super();
System.out.println("Constructing Ball");
}
public void setRadius(double r){
this.radius=r;
}
public double getRadius(){
return radius;
}
public double getArea() {
return 4.0*Math.PI*radius*radius;
}
public double getVolume(){
return 4.0/3.0*Math.PI*radius*radius*radius;
}
}
class Box extends Rectangle {
private double height;
private double width;
private double length;
public Box(){
System.out.println("Constructing Box");
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public double getWidth() {
return width;
}
@Override
public void setWidth(double width) {
this.width = width;
}
@Override
public double getLength() {
return length;
}
@Override
public void setLength(double length) {
this.length = length;
}
public double getArea() {
return 2.0*height*width+2.0*height*length+2.0*width*length;
}
public double getVolume(){
return height*width*length;
}
}
class Circle extends Shape {
private double radius;
public Circle(){
super();
System.out.println("Constructing Circle");
}
public Circle(double radius) {
super();
this.radius = radius;
System.out.println("Constructing Circle");
}
public void setRadius(double radius){
this.radius = radius;
}
public double getRadius(){
return radius;
}
@Override
public double getArea() {
return Math.PI*radius*radius;
}
}
class Rectangle extends Shape{
private double width;
private double length;
public Rectangle(){
System.out.println("Constructing Rectangle");
}
public Rectangle(double width, double length) {
this.width = width;
this.length = length;
System.out.println("Constructing Rectangle");
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
@Override
public double getArea() {
return width*length;
}
}
class Shape {
public Shape(){
System.out.println("Constructing Shape");
}
public double getArea(){
return 0.0;
}
}
(2)题目集6(7-5)
设计:
三个图形类继承了Shape类,继承了图形的方法(求面积,判断输入图形属性是否合法,toString)和属性;代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码);实现了多态。
题目及类图:
输入:从键盘首先输入三个整型值(例如a b c),分别代表想要创建的Circle、Rectangle及Triangle对象的数量,然后根据图形数量继续输入各对象的属性值(均为实型数),数与数之间可以用一个或多个空格或回车分隔。
输出
- 如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边关系),则输出
Wrong Format。 - 如果输入合法,则正常输出,输出内容如下(输出格式见输入输出示例):
- 各个图形的面积;
- 所有图形的面积总和;
- 排序后的各个图形面积;
- 再次所有图形的面积总和。

代码:
import static java.lang.StrictMath.sqrt;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int circlenum;
int rectanglenum;
int trianglenum;
double all=0;
Collection area = new ArrayList();
Circle circle = new Circle();
Rectangle rectangle = new Rectangle();
Triangle triangle = new Triangle();
Scanner scanner = new Scanner(System.in);
circlenum = scanner.nextInt();
rectanglenum = scanner.nextInt();
trianglenum = scanner.nextInt();
if(circlenum<0||rectanglenum<0||trianglenum<0){
System.out.println("Wrong Format");
System.exit(0);
}
for(int i=0;i<circlenum;i++){
circle.setRadius(scanner.nextDouble());
if (circle.validate()==true){
String a =String.format("%.2f",circle.getArea());
area.add(a);
}
else {
System.out.println("Wrong Format");
System.exit(0);
}
}
for(int j=0;j<rectanglenum;j++){
rectangle.setWidth(scanner.nextDouble());
rectangle.setLength(scanner.nextDouble());
if (rectangle.validate()==true){
String b=String.format("%.2f",rectangle.getArea());
area.add(b);
}
else {
System.out.println("Wrong Format");
System.exit(0);
}
}
for(int k=0;k<trianglenum;k++){
triangle.setSide1(scanner.nextDouble());
triangle.setSide2(scanner.nextDouble());
triangle.setSide3(scanner.nextDouble());
if(triangle.validate()==true){
String c=String.format("%.2f",triangle.getArea());
area.add(c);
}
else {
System.out.println("Wrong Format");
System.exit(0);
}
}
System.out.println("Original area:");
Object[] arr1=area.toArray();
double[] arr2=new double[area.size()];
for(int m=0;m<area.size();m++){
arr2[m]=new Double(arr1[m].toString());
System.out.print(String.format("%.2f",arr2[m])+" ");
all=all+arr2[m];
}
System.out.print("\n");
System.out.println("Sum of area:"+String.format("%.2f",all));
for(int o=0;o<arr2.length;o++){
for (int p=o+1;p<arr2.length;p++){
double flag;
if(arr2[o]>arr2[p]){
flag = arr2[o];
arr2[o]=arr2[p];
arr2[p]=flag;
}
}
}
System.out.println("Sorted area:");
for(int q=0;q<arr2.length;q++){
System.out.print(String.format("%.2f",arr2[q])+" ");
}
System.out.print("\n");
System.out.println("Sum of area:"+String.format("%.2f",all));
}
}
class Circle extends Shape{
private double radius;
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public double getArea(){
return 3.1415926*radius*radius;
}
@Override
public boolean validate() {
if(radius<=0){
return false;
}
else {
return true;
}
}
@Override
public String toString() {
return "Circle{" +
"radius=" + radius +
'}';
}
}
class Rectangle extends Shape{
private double width;
private double length;
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
@Override
public double getArea(){
return width*length;
}
@Override
public boolean validate() {
if(width<=0||length<=0){
return false;
}
else {
return true;
}
}
@Override
public String toString() {
return "Rectangle{" +
"width=" + width +
", length=" + length +
'}';
}
}
class Triangle extends Shape {
private double side1;
private double side2;
private double side3;
public double getSide1() {
return side1;
}
public void setSide1(double side1) {
this.side1 = side1;
}
public double getSide2() {
return side2;
}
public void setSide2(double side2) {
this.side2 = side2;
}
public double getSide3() {
return side3;
}
public void setSide3(double side3) {
this.side3 = side3;
}
@Override
public double getArea() {
return sqrt((side1+side2+side3)/2*((side1+side2+side3)/2-side1)*((side1+side2+side3)/2-side2)*((side1+side2+side3)/2-side3));
}
@Override
public boolean validate() {
if(side1<=0||side2<=0||side3<=0||side1+side2<=side3||side1+side3<=side2||side2+side3<=side1){
return false;
}
else {
return true;
}
}
@Override
public String toString() {
return "Triangle{" +
"side1=" + side1 +
", side2=" + side2 +
", side3=" + side3 +
'}';
}
}
abstract class Shape {
public double getArea(){
return 0;
}
public boolean validate(){
return false;
}
@Override
public String toString() {
return "Shape{}";
}
}
(3)题目集6(7-6)
设计:
定义一个接口类,里面写了一个求面积的方法,然后Circle类和Rectangle类实现了接口里面的方法,完成了要求功能求面积。
题目和类图:
在Main类的主方法中分别定义一个圆类对象及矩形类对象(其属性值由键盘输入),使用接口的引用分别调用圆类对象及矩形类对象的求面积的方法,直接输出两个图形的面积值。(要求只保留两位小数)

代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
double radius;
double width;
double length;
Circle circle = new Circle();
Rectangle rectangle = new Rectangle();
Scanner scanner = new Scanner(System.in);
radius = scanner.nextDouble();
width = scanner.nextDouble();
length = scanner.nextDouble();
circle.setRadius(radius);
rectangle.setWidth(width);
rectangle.setLength(length);
if(circle.check()==true){
if(rectangle.check()){
System.out.println(String.format("%.2f",circle.getArea()));
System.out.println(String.format("%.2f",rectangle.getArea()));
}
else {
System.out.println("Wrong Format");
}
}
else {
System.out.println("Wrong Format");
}
}
}
interface GetArea {
public double getArea();
}
class Circle implements GetArea {
double radius;
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return 3.1415926*radius*radius;
}
public boolean check(){
if(radius<=0){
return false;
}
else {
return true;
}
}
}
class Rectangle implements GetArea {
double width;
double length;
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
@Override
public double getArea() {
return width*length;
}
public boolean check(){
if(width<=0 || length<=0){
return false;
}
else {
return true;
}
}
}
三.对三次题目集中用到的正则表达式技术的分析总结
1 数字:[1]*$
2 n位的数字:^\d{n}$
3 至少n位的数字:^\d{n,}$
4 m-n位的数字:^\d{m,n}$
5 零和非零开头的数字:^(0|[1-9][0-9]*)$
6 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
7 带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$
8 正数、负数、和小数:^(-|+)?\d+(.\d+)?$
9 有两位小数的正实数:[2]+(.[0-9]{2})?$
10 有1~3位小数的正实数:[3]+(.[0-9]{1,3})?$
11 非零的正整数:[4]\d$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]*$
12 非零的负整数:^-[1-9][]0-9"$ 或 ^-[1-9]\d$
13 非负整数:^\d+$ 或 [5]\d*|0$
14 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
15长度为3-20的所有字符:^.{3,20}$
16 由26个英文字母组成的字符串:[8]+$
17由26个大写英文字母组成的字符串:[9]+$
18 由26个小写英文字母组成的字符串:[10]+$
19由数字和26个英文字母组成的字符串:[11]+$
四.采坑心得:
源码提交时经常会出现格式错误,或者直接答案错误,原因是没有按照题目要求格式输出
五.总结
通过这三次题目集的训练,我加强了对继承的使用,子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。更加熟悉了构造方法的使用,当类实例化一个对象时会自动调用构造方法。getter和setter方法的自动生成。
学会了如何如何求日期下n天,求前n天,求两个日期相差天数,锻炼了我的逻辑思维能力和解决问题能力。
锻炼了我的合并两个升序排序的整型数组为一个新的升序整型数组并输出的能力,更加熟练了插入排序、选择排序及冒泡排序三种算法的使用
训练了我正则表达式的使用,加深了我对正则表达式的理解,还有对接口的使用。
浙公网安备 33010602011771号