(1). 运行以下三个程序,对每一行语句加上注释,并对每一个程序的每一个输出结果给出分析。在报告中附上程序截图和详细的文字说明。
public class first_1 {
public static void main(String []args){
System.out.println("Hi, ABC, good".matches("ABC "));//matches判断所给字符串是否匹配给定(ABC )正则表达式,不匹配,返回false
System.out.println("Hi, ABC, good".matches(".*ABC.*"));//.*ABC.*与所给字符串匹配,返回true
System.out.println("A,B;C".replaceAll(",;","#"));//replaceAll方法想将”,;“替换成”#“,原字符串没有”,;“,则没有变化
System.out.println("A,B;C".replaceAll("[,;]","#"));//正则表达式[,;]通过replaceAll方法将字符中所有”,“,”;“替换成”#“
String []tokens="A,B;C".split("[,;]");//正则表达式[,;]通过split方法将字符中所有”,“,”;“作为分割符将原字符串分割
for(int i=0;i<tokens.length;i++)//i<tokens的长度前继续循环
System.out.println(tokens[i]+" ");//输出split后的tokens的单个字符,每个字符占一行
}
}
public class first_2 {
public static void main(String []args){//main方法
String s="Hi, Good Morning";//定义一个字符串s并对其赋值为”Hi, Good Morning“
System.out.println(m(s));//输出以s为参数的m方法的返回值,m的定义在下面
}
public static int m(String s){//以字符串s为形参,int为返回类型的共有静态方法m的定义
int count = 0;//定义一个int型变量count,并初始化为0
for(int i=0;i<s.length();i++){//i初始化为0,i<s的长度时执行循环
if(Character.isUpperCase(s.charAt(i)))//如果以i下标的s字符为大写英文字母,执行下面语句
count++;//count的值加一
}
return count;//将count做为返回值
}
}
public class first_3 {
public static void main(String []args){//main方法
String s="java";//定义String类型的变量s并初始化为“java”
StringBuilder builder=new StringBuilder(s);//以s为参数定义StringBuilder类型的变量builder
change(s,builder);//将s,builder作为实参执行change方法
System.out.println(s);//输出change方法后的s
System.out.println(builder);//输出change方法后的builder
}
private static void change(String s,StringBuilder builder){//以是s,builder为形参void为返回类型的私有静态方法change的定义
s=s+" and HTML";//企图在s后面加上“and HTML”
//但是在方法change里面的s不是main里面的s(值传递),所以在退出方法change后s末尾并未被加上“HTML”
builder.append(" and HTML");//用StringBuilder中的append方法在builder字符串后面加上“and HTML”
}
}
2). 抽象类和接口的实验。
(2.1) 定义一个抽象类Human:包含一个成员变量String name;构造方法Human(String name),用于初始化姓名name;一个抽象方法double sayHi()。在报告中附上程序截图和详细的文字说明。
package second;
public abstract class Human {//抽象类Human
String name;//成员变量name
Human(String name){//以name为参数的构造方法
this.name=name;//因为重名所以用this所指出的成员变量name被形参name赋值
}
public abstract double sayHi();//一个抽象方法double sayHi()
}
(单个抽象类无法执行,执行结果放1.3)
(2.2) 定义三个继承抽象类Human的类,分别命名为Chinese、Japanese和English,在这三个类中重写sayHi()方法,分别输出一句中文、日文和英文的问候;在报告中附上程序截图、运行结果和详细的文字说明。
三个类的定义都是类似的:
Chinese类:
package second;
public class Chinese extends Human{
Chinese(String name){//构造方法的实现
super(name);//调用父类构造 tips必须是构造方法中都第一条语句
}
public double sayHi(){//抽象成员方法的实现
System.out.println("Hi, I'm"+name);//输出name为了测试是否继承了成员变量
return 0;
}
}
English类:
package second;
public class English extends Human{
English(String name){//构造方法的实现
super(name);//调用父类构造 tips必须是构造方法中都第一条语句
}
public double sayHi(){//抽象成员方法的实现
System.out.println("Hi, I'm"+name);//输出name为了测试是否继承了成员变量
return 0;
}
}
Japanese类:
package second;
public class Japanese extends Human{
Japanese(String name){//构造方法的实现
super(name);//调用父类构造 tips必须是构造方法中都第一条语句
}
public double sayHi(){//抽象成员方法的实现
System.out.println("Hi, I'm"+name);//输出name为了测试是否继承了成员变量
return 0;
}
}
(未定义main方法,执行结果放2.3)
(2.3) 定义一个测试类HumanTest:创建一个包含3个Human对象的数组,3个Human对象来自Chinese、Japanese和English类,循环调用该数组中的元素的sayHi()方法。在报告中附上程序截图、运行结果和详细的文字说明。
因为要用Human对象调用3者,可知这是上转型变量的数组
代码如下:
package second;
public class Human_test {
public static void main(String []args){
System.out.println("抽象类实现上转型对象:");
Human []human=new Human[3];//创建human数组
human[0]= new Chinese("Chinese");
human[1]=new English("English");
human[2]=new Japanese("Japanese");//human数组变量分别是3者的上转型
for(int i=0;i<3;i++) human[i].sayHi();
}
}
名字输出正确,打招呼方法与想对应子类对应,代码执行成功。
(2.4) 通过一个接口(命名为Human)和三个实现类(命名为Chinese、Japanese和English)来达到如上类似的效果。在报告中附上程序截图、运行结果和详细的文字说明。
接口:
package second_new;
public interface Human {
double sayHello();
}
三个类:
package second_new;
public class Chinese implements Human{
String name;//接口中只能有final数据类型,所以name放在这里
Chinese(String name){//构造方法的实现
this.name=name;
}
public double sayHello(){//抽象成员方法的实现
System.out.println("Hello, I'm "+name);//输出name为了测试是否实现了抽象的接口方法
return 0;
}
}
package second_new;
public class English implements Human{
String name;//接口中只能有final数据类型,所以name放在这里
English(String name){//构造方法的实现
this.name=name;
}
public double sayHello(){//抽象成员方法的实现
System.out.println("Hello, I'm "+name);//输出name为了测试是否实现了抽象的接口方法
return 0;
}
}
package second_new;
public class Japanese implements Human{
String name;//接口中只能有final数据类型,所以name放在这里
Japanese(String name){//构造方法的实现
this.name=name;
}
public double sayHello(){//抽象成员方法的实现
System.out.println("Hello, I'm "+name);//输出name为了测试是否实现了抽象的接口方法
return 0;
}
}
测试类:
package second_new;
public class interface_test {
public static void main(String []args){
System.out.println("接口实现上转型对象:");
Human[] human=new Human[3];//创建human数组
human[0]= new Chinese("Chinese");
human[1]=new English("English");
human[2]=new Japanese("Japanese");
for(int i=0;i<3;i++) human[i].sayHello();
}
}
运行成功!
(3). 编写Java应用程序,计算菜单“北京烤鸭:199.1元;西芹炒肉:11.8元;酸菜鱼:59.1元;铁板牛柳:32.1元”的总价格。在报告中附上程序截图、完整的运行结果截图和简要文字说明。
由题可知,这道题主要对题目的这个字符串进行处理,将菜名和菜的价格从字符串中提出,我想到的是用Scanner提供的分隔符切割提取的方法
源代码如下(只有一个主方法)
其中的正则表达式[;元:]是因为菜名和价格之间都是隔着这些字符
package third;
import java.util.*;
import java.util.Scanner;
public class menu {
public static void main(String []args){
String s1=("北京烤鸭:199.1元;西芹炒肉:12.9元;酸菜鱼:59元;铁板牛柳:32.1元");
Scanner menu =new Scanner(s1);
menu.useDelimiter("[:元;]");//自定义正则表达式作为分隔标记
double []price=new double[4];//保存菜价
String []name=new String[4];//保存菜名
int i=0,j=0;//i,j后面分别作为price和name的数组下标
double sum=0;//sum作为总价最后输出
while(menu.hasNext()){
try{//读入double数据
double num= menu.nextDouble();//这里用num记录下nextDouble的值
price[i++]= num;
sum+=num;//若用两次nextDouble就会出错
}//被分隔分开的不是double数,由正则表达式可知保存的是菜名
catch(InputMismatchException exp) {
name[j++]= menu.next();
}//while中catch利用异常处理方法获得菜名
}
for(int ii=0;ii<name.length;ii++){//i已经被定义过了,不能重定义,就用ii啦
System.out.println(name[ii]+"的价格是:"+price[ii]+"元");
}
System.out.println("总价是:"+sum);//输出总价
}
}
菜名和价格都输出准确,最后的总价也计算正确,代码执行成功
(4). 编写Java应用程序,每次从键盘读入一个包含有大写英文字母、小写英文字母和数字混杂的字符串(例如Aa123bEFGaaa49023),要求按顺序输出大写英文字母(例如AEFG)、小写英文字母(abaaa)和数字(12349023)。要求循环连续测试10次,在报告中附上程序截图、完整的运行结果截图和简要文字说明。
由题我想到了正则表达式及字符串的替换与分解的用法
源代码:
package fourth;
import java.util.*;
import java.util.regex.*;
public class four {
public static void main(String []args){
for(int i=0;i<10;i++){
System.out.print("Please input your string:");
Scanner input=new Scanner(System.in);
String s=input.nextLine();//s保留输入的字符串,设为输入一整行
Pattern p;
Matcher m;
p=Pattern.compile("[A-Z]+");//正则化表达式,取A到Z字符
m=p.matcher(s);
System.out.print("The following is majuscule:");
while(m.find()){
String str=m.group();
System.out.print(str);
}
System.out.println();
p=Pattern.compile("[a-z]+");正则化表达式,取a到z字符
m=p.matcher(s);
System.out.print("The following is minuscule:");
while(m.find()){
String str=m.group();
System.out.print(str);
}
System.out.println();
p=Pattern.compile("[\\d+]");正则化表达式,取阿拉伯数字
m=p.matcher(s);
System.out.print("The following is number:");
while(m.find()){
String str=m.group();
System.out.print(str);
}
System.out.println();
}
}
}
运行结果(题目给的自己瞎搞了几组数据,好像没什么大问题了)。
(5)编写Java应用程序,统计分析网页About-Shenzhen University (SZU) 中关于深圳大学的介绍的英文文章(包括题目About)中每个英文单词出现的次数(不区分大小写,不要写爬虫,可以把整篇文章的内容当作一个字符串读入),并输出出现次数最多的50个英文单词(按出现次数排序,每行输出10个英文单词,共5行)。在报告中附上程序截图、完整的运行结果截图和简要文字说明。
文本预处理,把换行符全去了,将整篇文章作为一行输入(太菜了,只能这样了QAQ)
代码:
package fifth;
import java.util.*;
import static java.lang.Character.*;
public class web {
public static void main(String []args){
Scanner input= new Scanner(System.in);
StringBuilder article=new StringBuilder();//article存放输入的文章
article.append(input.nextLine());
for(int i=0;i<article.length();i++)
if(isUpperCase(article.charAt(i)))
article.setCharAt(i,toLowerCase(article.charAt(i)));//将article里面的所有大写字母转为小写
String[] words=article.toString().split("[^a-z']");//将^和a~z之外的所有字符作为分隔符
HashMap<String,Integer> map=new HashMap<>();//统计单词数的图
for(String word:words) {//若拆分出来的字符不为空串,则统计出现的次数
if (word.equals("")) continue;
if (map.containsKey(word))
map.replace(word, map.get(word) + 1);//若已经存在该单词的键,则对应的值+1
else map.put(word, 1);//若不存在该单词的键,则将其对应的值设为1
}
List<Map.Entry<String,Integer>> list=new ArrayList<>(map.entrySet());//将哈希表中的键值对转化成List
list.sort((o1,o2)->o2.getValue().compareTo(o1.getValue()));//降序排序
for(int i=0;i<5;i++){//输出出现次数最多的前50个单词
for(int j=0;j<10;j++)
System.out.printf("%s:%d ",list.get(i*10+j).getKey(),list.get(i*10+j).getValue());//每个单词占20个字符,左对齐
System.out.println();
}
}
}
(6). 张三、李四等人是A社团成员,李四、王五等人是B社团成员,编写一个Java应用程序(要求使用集合类),输出参加A社团的人、参加B社团的人、以及同时参加两个社团的人。在报告中附上程序截图、完整的运行结果截图和详细的文字说明。(10分)
这道题中李四即是A社团的成员又是B社团的成员,他是A社团和B社团的交集,在学的集合类中,HashSet是一个可以求交、并集的类,所以这道题我用了HashSet求交集
源代码如下:
package fifth;
import java.util.*;
import java.util.HashMap;
public class six {
public static void main(String args[]){
HashSet<String> A=new HashSet<String>();//A社团初始化
A.add("张三");
A.add("李四");
System.out.print("A的社团成员有:");
Object []a=A.toArray();
for(int i=0;i<A.size();i++)//输出A社团成员
System.out.print(a[i]+" ");
HashSet<String> B=new HashSet<String>();//B社团成员初始化
B.add("李四");
B.add("王五");
System.out.print("\nB社团成员有:");
Object []b=B.toArray();
for(int i=0;i<B.size();i++)
System.out.print(b[i]+" ");
B.retainAll(A);//求A社团和B社团的交集,求到的赋值给B
System.out.print("\n同时参加两个社团的人有:");
Object []c=B.toArray();
for(int i=0;i<B.size();i++)//输出同时参加两个社团的人
System.out.print(c[i]+" ");
System.out.println();
}
}
(7). 有10个国家,其属性有name、GDP2020和COVID19,分别表示国家名称、国际货币基金组织公布的2020年的国内生产总值(单位:百万美元)和网易新闻2021年10月7日公布的新冠肺炎累计确诊人数。10个国家的信息如下:
package seven;
import java.util.*;
class country {//利用country存放每个国家的信息
String name;//国家名字
Integer GDP2020,COVID19;//2020年GDP、2019年确诊人数
public country(String name,int GDP2020,int COVID19){//有参构造初始化
this.name=name;
this.GDP2020=GDP2020;
this.COVID19=COVID19;
}
public String toString(){//格式化
return String.format("%-10s%s",name,"GDP2020:"+GDP2020+"COVID19"+COVID19);
}
}
public class seven {
public static void main(String args[]){
Scanner input=new Scanner(System.in);
TreeMap<country,Integer>map=new TreeMap<>(new Comparator<country>() {
public int compare(country c1,country c2){//重写compare
return c1.COVID19.compareTo(c2.COVID19);//升序排序
}
});
for(int i=0;i<10;i++){
String name=input.next();
int GDP2020=input.nextInt();
int COVID19=input.nextInt();
map.put(new country(name,GDP2020,COVID19),COVID19);
}
for(country c:map.keySet())
System.out.println(c);
}
}
其他(例如感想、建议等等)。
这次实验是做的时间最长的一次了,主要的困难在第六题,一开始我是想这正常输入的,但是使用while(input.hasNextLine())时始终无法跳出循环,询问助教后也没有很好的解决方法,于是在助教的认同下先对文本进行处理后进行输入(删除换行符)。