Java第六次作业 1502 马 帅
《Java技术》第六次作业
(一)学习总结
2.如下代码:
public class PrintExceptionStack {
public static void main( String args[] )
{
try {
method1();
} catch ( Exception e ) {
System.err.println( e.getMessage() + "\n" );
e.printStackTrace();
}
}
public static void method1() throws Exception
{
method2();
}
public static void method2() throws Exception
{
method3();
}
public static void method3() throws Exception
{
throw new Exception( "Exception thrown in method3" );
}
}
运行结果如图所示:
其中printStackTrace方法的输出结果为:
getMessage 方法的输出结果为:
传播过程:首先通过try{}监视代码块,若在此段代码中出现异常,由catch{}中的代码进行处理。在上述代码中,异常由method3()产生异常,通过method2()和method1()传入try中进行捕获,通过catch进行处理。
3.如下代码:
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Collection<String> books = new ArrayList<String>();
books.add("One book");
books.add("Two book");
books.add("Three book");
System.out.println("原始元素之后:"+books);
Iterator<String> it = books.iterator();
while(it.hasNext())
{
String book = (String)it.next();
System.out.println(book);
if (book.equals("One book"))
{
books.remove(book);
}
}
System.out.println("移除元素之后:"+books);
}
}
运行结果如图所示:
若删除的是集合中的最后一个元素,运行结果如下:
删除时出现了错误,因为此段代码中调用的remove方法是集合自身的方法,内容会被删除,但破坏了集合本身的内容,迭代出现错误,所以才会停止。
若删除的是最后一个元素,可以输出结果但仍有错误,原因同理,在删除之后破坏了集合,使迭代无法继续,所以出现错误。
若要删除集合中的元素,应调用Iterator的remove方法,代码如下:
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Collection<String> books = new ArrayList<String>();
books.add("One book");
books.add("Two book");
books.add("Three book");
System.out.println("原始元素之后:"+books);
Iterator<String> it = books.iterator();
while(it.hasNext())
{
String book = (String)it.next();
System.out.println(book);
if (book.equals("One book"))
{
it.remove();
}
}
System.out.println("移除元素之后:"+books);
}
}
4.如下代码:
import java.util.*;
class Student {
String id;
String name;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
public String toString() {
return "Student id=" + id + ", name=" + name ;
}
}
public class Test
{
public static void main(String[] args)
{
HashSet<Student> set = new HashSet<Student>();
set.add(new Student("1","Jack"));
set.add(new Student("2","Rose"));
set.add(new Student("2","Rose"));
System.out.println(set);
}
}
输出结果为:
[Student id=2, name=Rose, Student id=1, name=Jack, Student id=2, name=Rose]
显然,使用HashSet却存入了相同的元素,因为HashSet依靠Object类的hashCode()方法和equals()方法完成重复元素的判断,所以若想去掉重复元素,必须要重写hashCode()方法和equals()方法。
覆写hashCode()方法和equals()方法,代码如下:
import java.util.*;
class Student {
String id;
String name;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
public String toString() {
return "Student id=" + id + ", name=" + name ;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class Test
{
public static void main(String[] args)
{
HashSet<Student> set = new HashSet<Student>();
set.add(new Student("1","Jack"));
set.add(new Student("2","Rose"));
set.add(new Student("2","Rose"));
System.out.println(set);
}
}
5.在hashCode()方法中,eclipse定义了一个系数 final int prime = 31; 为什么这个系数是31呢?为什么就不是32或者21呢?之所以乘以31,其实就是为了尽量保证每个对象的哈希值唯一。在存储的时候可以只通过hashCode方法就可以确定其唯一性,就不用再去麻烦equals方法了。31是个素数(一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数),这样的数所存在的公倍数就很少。数据存储和查找都是通过hash地址值,所以尽量保证我们得到的哈希值和真实地址值一一对应,从而提高查找效率,而乘以31这个系数可以保证哈希值足够大,而减少重复,也可以保证得出来的哈希值不溢出。
(二)实验总结
1.模拟KTV点歌系统,分别用LinkedList和ArrayList集合,实现一个模拟KTV点歌系统的程序。实现以下功能:
(1)显示歌曲列表
(2)添加歌曲到列表
(3)删除歌曲
(4)将歌曲置顶
(5)将歌曲前移一位
(6)退出
题目扩展:歌曲包括曲名、演唱者。增加排序显示歌曲列表功能。
- 程序设计思路:
(1)使用LinkedList集合:
首先创建LinkedList集合的对象,并向里面初始化一些数据,利用switch..case进行功能的选择;
添加时,直接添加歌曲名称,其他操作都输入歌曲的序号;
前移时,使用临时变量进行调换;
在置顶操作时,使用addFirst()方法置顶,并删除原来的元素。
(2)使用ArrayList集合:
首先创建ArrayList集合的对象,并向里面初始化一些数据,利用switch..case进行功能的选择;
添加时,直接添加歌曲名称,其他操作都输入歌曲的序号;
前移时,使用临时变量进行调换;
在置顶操作时,使用add(0,element)方法置顶,并删除原来的元素。
(3)扩展:
使用ArrayList集合;
声明Init类对歌名和歌手构造方法;
所有操作与上述使用ArrayList集合的方法相同;
新增一个选项进行排序。 - 实验问题分析:
问题:怎样通过拼音对对象数组进行排序?
解决方案:
在网上找到了解决方法:Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);
声明一个String泛型的ArrayList集合,用来保存歌名;
将歌名从原来的集合中复制到这个集合中,并将它转换为字符数组songname[],调用Arrays.sort(songname,cmp)排序;
按照排好序的歌名对原集合查找,每找到一个元素就将它复制添加到集合尾部,并将原来的元素删除。
注意:
只有当需要排序时才能进行排序,若每执行一次switch..case的其他方法便排序,置顶与前移功能将不能正确输出;
保存歌名的集合要在排序之后清空。
2.模拟微博用户注册
用HashSet实现一个模拟微博用户注册的程序。用户输入用户名、密码、确认密码、生日(格式yyyy-mm-dd)、手机号码(11位,13、15、17、18开头)、邮箱信息进行微博的注册。要求对用户输入的信息进行验证,输入信息正确后,验证是否重复注册,如果不是则注册成功,否则注册失败。
提示:
(1)设计一个用户类存储用户注册信息
(2)设计一个校验信息类,定义校验方法完成对输入信息的校验。学习使用正则表达式完成对生日、手机号码和邮箱的验证。
(3)设计一个用户注册类模拟注册过程。用HashSet存储用户数据列表,定义一个initData()方法添加初始用户信息。在main方法中完成用户注册功能。
-
程序设计思路:
(1)建立一个UsersInformation类用来储存用户的信息;
(2)建立一个Check类,里面定义若干方法,用正则表达式分别判断用户输入的各个信息是否符合规则;
(3)在主方法里初始化几个用户信息;
(4)使用do..while循环进行多次注册,使用switch..case进行判断是注册还是退出;
(5)在所有信息确认无误后,使用initData方法进行添加完成注册。 -
实验问题分析:
问题1:判断输入信息是否重复
原因:开始时我对每个信息分别进行判断,导致程序出现异常,原因是使用iterator的next()方法时,没有复位,导致hasNext()始终没有其他值。
解决方案:将信息全部录入后,进行统一的查重。
问题2:相同的手机或邮箱或用户名而其他两个元素有一个不同,都会被认定为是不同元素
原因:覆写hashCode()方法中,当用户名、手机、邮箱的值有一个不同,就会返回不同的值,就会被认定为元素不重复。
解决方案:覆写hashCode()方法,使其返回常数1,使其必须调用覆写的equals()方法,在equals()方法中进行具体的判断。
注:只要用户名不同则判断为不同的元素,进行输入。
(三)代码托管
- 码云commit历史截图