一、 实验目的
1. 熟悉集合类的应用,掌握接口的定义、实现类的编写和接口回调等技术。
二、实验内容与要求
1. 抽象类和接口的实验。(24分)
(1.1) 定义一个抽象类Human:包含一个成员变量String name;构造方法Human(String name),用于初始化姓名name;一个抽象方法double sayHello()。在报告中附上程序截图和详细的文字说明。(6分)
(1.2) 定义三个继承抽象类Human的类,分别命名为Chinese、Japanese和English,在这三个类中重写sayHello()方法,分别输出一句中文、日文和英文的问候;在报告中附上程序截图、运行结果和详细的文字说明。(6分)
(1.3) 定义一个测试类HumanTest:创建一个包含3个Human对象的数组,3个Human对象来自Chinese、Japanese和English类,循环调用该数组中的元素的sayHello()方法。在报告中附上程序截图、运行结果和详细的文字说明。(6分)
(1.4) 通过一个接口(命名为Human)和三个实现类(命名为Chinese、Japanese和English)来达到如上类似的效果。在报告中附上程序截图、运行结果和详细的文字说明。(6分)
2. 编写Java应用程序,计算菜单“北京烤鸭:199.1元;西芹炒肉:12.9元;酸菜鱼:59元;铁板牛柳:32.1元”的总价格。在报告中附上程序截图、完整的运行结果截图和简要文字说明。(16分)
3. 张三、李四等人是A社团成员,李四、王五等人是B社团成员,编写一个Java应用程序(要求使用集合类),输出参加A社团的人、参加B社团的人、以及同时参加两个社团的人。在报告中附上程序截图、完整的运行结果截图和详细的文字说明。(20分)
4. 有8个显示器,其属性有尺寸和价格。编写一个Java应用程序,使用TreeMap<K,V>,按照价格从小到达排序输出所有显示器的信息,要求通过两种方式实现:通过实现Comparator接口和通过实现Comparable接口。在报告中附上程序截图、完整的运行结果截图和详细的文字说明。(20分)
三、实验过程及结果
1. 抽象类和接口的实验。
(1.1) 定义一个抽象类Human:包含一个成员变量String name;构造方法Human(String name),用于初始化姓名name;一个抽象方法void sayHello()。
(1.2) 定义三个继承抽象类Human的类,分别命名为Chinese、Japanese和English,在这三个类中重写sayHello()方法,分别输出一句中文、日文和英文的问候。
class Chinese extends Human{ //Chinese类继承Human
public Chinese(String name) {
super(name);
}
public void sayHello() { //重写sayHello()方法
System.out.printf("你好!我叫%s。\n", name);
}
}
class Japanese extends Human{ //Japanese类继承Human
public Japanese(String name) {
super(name);
}
public void sayHello() { //重写sayHello()方法
System.out.printf("こんにちは 私は%sです\n", name);
}
}
class English extends Human{ //English类继承Human
public English(String name) {
super(name);
}
public void sayHello() { //重写sayHello()方法
System.out.printf("Hello! My name is %s.\n", name);
}
}
public class Example { //主类
static public void main(String []args) {
Human chinese = new Chinese("小明"); //声明chinese对象
chinese.sayHello(); //用chinese对象调用sayHello()方法
Human japanese = new Japanese("はるな"); //声明japanese对象
japanese.sayHello(); //用japanese对象调用sayHello()方法
Human english = new English("Lisa"); //声明english对象
english.sayHello(); //用english对象调用sayHello()方法
}
}
(1.3) 定义一个测试类HumanTest:创建一个包含3个Human对象的数组,3个Human对象来自Chinese、Japanese和English类,循环调用该数组中的元素的sayHello()方法。
class HumanTest{
private Human human[]; //创建一个包含3个Human对象的数组,3个Human对象来自Chinese、Japanese和English类
public HumanTest(Human hu[]) {
human = new Human[3]; //用new关键字开辟一个长度为3的数组空间,为Human类型
for(int i = 0; i < 3; i++) {
this.human[i] = hu[i]; //初始化每个human对象
}
}
public void display() {
//分别创建三个实现类的对象
Human [] human = new Human[3];
human[0] = new Chinese("小明");
human[1] = new Japanese("はるな");
human[2] = new English("Lisa");
//循环调用该数组中的元素的sayHello()方法
for(int i = 0; i < 3; i++) {
human[i].sayHello();
}
}
}
public class Example {
static public void main(String []args) {
Human [] human = new Human[3]; //分配内存空间供Human类数组使用,其元素个数为3
HumanTest test = new HumanTest(human); //声明HumanTest类对象test
test.display(); //用test对象调用display()方法
}
}
(1.4) 通过一个接口(命名为Human)和三个实现类(命名为Chinese、Japanese和English)来达到如上类似的效果。
package example2;
interface Human{ //定义接口
abstract void sayHello(); //声明抽象方法
}
class Chinese implements Human{ //用implements关键字继承Human接口
public void sayHello() { //重写sayHello()方法
System.out.println("你好!我叫小明。");
}
}
class Japanese implements Human{
public void sayHello() {
System.out.println("こんにちは 私ははるなです");
}
}
class English implements Human{
public void sayHello() {
System.out.println("Hello! My name is Lisa.");
}
}
class HumanTest{
private Human human[];
public HumanTest(Human hu[]) {
human = new Human[3];
for(int i = 0; i < 3; i++) { //初始化每个human对象
this.human[i] = hu[i];
}
}
public void display() {
Human [] human = new Human[3]; //用new关键字开辟一个长度为3的数组空间,为Human类型
//分别创建三个实现类的对象
human[0] = new Chinese();
human[1] = new Japanese();
human[2] = new English();
//循环调用该数组中的元素的sayHello()方法
for(int i = 0; i < 3; i++) {
human[i].sayHello();
}
}
}
public class Test{
static public void main(String []args) {
Human chinese = new Chinese(); //创建Chinese对象chinese
chinese.sayHello(); //调用sayHello()方法
Human japanese = new Japanese();
japanese.sayHello();
Human english = new English();
english.sayHello();
Human [] human = new Human[3];//创建Human对象数组human,长度为3
HumanTest test = new HumanTest(human);//创建HumanTest对象test,传入human数组
test.display();//用test对象调用display()方法
}
}
2. 编写Java应用程序,计算菜单“北京烤鸭:199.1元;西芹炒肉:12.9元;酸菜鱼:59元;铁板牛柳:32.1元”的总价格。
package example2;
import java.util.*;
public class Compute {
public static void main(String[] args) {
Map<String, Double> menu = new HashMap<>();//用Map接口声明HashMap实现类,new了一个新对象menu
//将四种菜品名字及价格用put添加进menu集合中
menu.put("北京烤鸭", (double)199.1);
menu.put("西芹炒肉", (double)12.9);
menu.put("酸菜鱼", (double)59);
menu.put("铁板牛柳", (double)32.1);
double sum = 0;
//通过Map.entrySet()使用Iterator迭代器遍历menu集合的key和value,Map.Entry是Map声明的一个内部接口,此接口为泛型,Entry<K,V>表示Map中的一个实体(一个key-value键值对)。
Iterator<Map.Entry<String, Double>> it = menu.entrySet().iterator();
while (it.hasNext()) {//当获取的键值对非空时,进行while里的操作
Map.Entry<String, Double> entry = it.next();
sum = sum + entry.getValue();//entry.getValue()获取entry里的value,即每样菜品的价格
}
System.out.println("北京烤鸭、西芹炒肉、酸菜鱼和铁板牛柳的总价格为: " + sum);
}
}
3、张三、李四等人是A社团成员,李四、王五等人是B社团成员,编写一个Java应用程序(要求使用集合类),输出参加A社团的人、参加B社团的人、以及同时参加两个社团的人。
package set;
import java.util.*;
public class Set {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入A社团成员数量:");
int n1 = scanner.nextInt();
System.out.println("请输入A社团成员:");
TreeSet<String> set1=new TreeSet<String>(); //创建树集合对象set1
for(int i = 0; i < n1; i++){
set1.add(scanner.next()); //向树集合添加元素
}
System.out.println("请输入B社团成员数量:");
int n2 = scanner.nextInt();
System.out.println("请输入B社团成员:");
TreeSet<String> set2=new TreeSet<String>(); //创建树集合对象set2
for(int i = 0; i < n2; i++){
set2.add(scanner.next()); //向树集合添加元素
}
for (String str : set1) {
System.out.print(str + " "); //输出树集合set1中的元素
}
System.out.println();
for (String str : set2) {
System.out.print(str + " "); //输出树集合set2中的元素
}
System.out.println();
set1.retainAll(set2); //求两个集合的交集retainAll()
Iterator<String> it = set1.iterator();//创建树集合set1的迭代器it
while(it.hasNext()){ //判断集合中是否还有后续元素
String s = (String) it.next();
System.out.print(s + " "); //输出两个集合的交集中的元素
}
scanner.close();
}
}
4. 有8个显示器,其属性有尺寸和价格。编写一个Java应用程序,使用TreeMap<K,V>,按照价格从小到达排序输出所有显示器的信息,要求通过两种方式实现:通过实现Comparator接口和通过实现Comparable接口。
通过实现Comparator接口:
package map;
import java.util.*;
class Indicator2 implements Comparator<Indicator2>{//定义Indicator2类继承Comparable接口
private double price; //定义成员变量price
public Indicator2(double price){ //带参构造函数
this.price = price;
}
public Indicator2(){} //无参构造函数
public double getPrice(){ //获取price
return this.price;
}
//重写compare()方法,按价格升序排序
public int compare(Indicator2 in1, Indicator2 in2) {
return in1.getPrice() > in2.getPrice()? 1 : -1;
}
//重写toString()方法
public String toString() {
return "\n价格为" + this.price + "元的显示器尺寸 ";
}
}
public class Map2 {
public static void main(String[] args) {
TreeMap<Indicator2, String> m = new TreeMap<Indicator2, String>(new Indicator2()); //创建TreeMap对象m;
//将元素添加到映射m中
m.put(new Indicator2(25), " 16寸");
m.put(new Indicator2(78), " 32寸");
m.put(new Indicator2(300), " 64寸");
m.put(new Indicator2(128), " 128寸");
m.put(new Indicator2(880), " 256寸");
m.put(new Indicator2(360), " 512寸");
m.put(new Indicator2(946), " 8寸");
m.put(new Indicator2(520), " 24寸");
System.out.println(m); //输出m中的元素(按价格升序排序)
}
}
通过实现Comparable接口:
package map;
import java.util.*;
@SuppressWarnings("rawtypes")//注解,忽略因使用泛型但未限制类型时所产生的警告
class Indicator implements Comparable {//定义Indicator类继承Comparable接口
double key = 0;
Indicator(double k) {
key = k;
}
//重写Comparable接口compareTo()方法,实现新的排序规则,如果this.key<=indicator.key,返回值为负,如果this.key>indicator.key,返回值为正,实现升序排序
public int compareTo(Object b) {
Indicator indicator = (Indicator) b;
if ((this.key - indicator.key) != 0)
return (int) (this.key - indicator.key);
return -1;
}
}
class Size_Price { //定义Size_Price类
int size;
double price;
Size_Price(int s, double p) {
size = s;
price = p;
}
}
public class Map {
public static void main(String[] args) {
TreeMap<Indicator, Size_Price> map = new TreeMap<Indicator, Size_Price>();
//用new创建TreeMap集合对象map
int size[]={16, 32, 64, 128, 256, 512, 8, 24};
double price[]={25, 78, 300, 128, 880, 360, 946, 520};
//创建一个长度为8的Size_Price类型数组对象sp,传入size与price的值
Size_Price sp[] = new Size_Price[8];
for (int i = 0; i < sp.length; i++) {
sp[i] = new Size_Price(size[i],price[i]);
}
Indicator key[]=new Indicator[8];
for (int i = 0; i < key.length; i++) {
key[i] = new Indicator(sp[i].size);
}
//将key与sp数组内的元素添加到map集合中
for (int i = 0; i < sp.length; i++) {
map.put(key[i], sp[i]);
}
//values():获取集合中的所有键值对象
Collection<Size_Price> collection = map.values();
//iterator():返回一个Iterator接口实现类对象,用来遍历集合。
Iterator<Size_Price> it = collection.iterator();
System.out.println("按价格升序排序后为:");
//集合非空时,依次输出按价格升序排完序后(已在map内部排好序)的显示器内存与价格
while (it.hasNext()) {
Size_Price indicator = it.next();
System.out.println(indicator.size + "寸 " + indicator.price + "元");
}
map.clear(); //把整个map清空
}
}