实验6 集合类
一、实验目的
了解集合的定义和分类,掌握List接口 、Set接口 、Map接口的实现类,掌握使用Collections工具类和Arrays工具类操作集合。
二、程序理解:
Java中的集合都是由一些接口,抽象类及它们的实现类所组成。而它们全部封装在java.util包中。
(1)List
下面的代码将利用LinkedList来实现一个栈的基本功能
import java.util.LinkedList;
public class MockStack {
private LinkedList data = new LinkedList();
public boolean idEmpty(){
return data.isEmpty();
}
public Object top(){
//取栈顶元素相当于取LinkedList容器的头位置的元素
return data.getFirst();
}
public void push(Object element){
//压入元素相当于在LinkedList容器的头位置插入元素
data.addFirst(element);
}
public void pop(){
//弹出元素相当于删除LinkedList容器的头位置的元素
data.removeFirst();
}
public String toString(){
return data.toString();
}
public static void main(String[] args){
MockStack stack = new MockStack();
//下面的语句使用LinkedList实现的堆栈的用法
stack.push("Shandong");
stack.push("University Of Technology");
stack.push("StephenLi");
while (!stack.idEmpty()){
System.out.println("即将弹出的成员是:" + stack.top());
stack.pop();
System.out.println("当前栈中剩余的成员为:" + stack);
}
}
}
运行结果:
(2)set
HashSet为快速查找而设计的Set,存入HashSet的对象必须定义HashCode方法,其底层实现是一个哈希表,存入HashSet中的元素没有顺序性。TreeSet为保持Set中成员有序而设计的一个Set的子类,存入TreeSet中的对象如果实现了Comparable接口,则将按照该接口的compareTo方法比较大小后按照升序排列,程序员也可以在构造方法中直接指定比较器。LinkedHashSet具有HashSet的查询速度,且底层使用链表维护元素的顺序,也就是说元素的顺序与插入的顺序相同(注意与TreeSet中元素的顺序区别)。
下面就演示一下这三种类型的Set的特点
package net.chelson.chapter9;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetTest {
//测试插入重复数据的情况
public void testRebundant(Set set) {
set.add("chelson");
set.add("chelson");
set.add("chelson");
System.out.println("插入重复数据后"+ set.getClass().getName() +"的成员为: " + set);
}
//测试set内部元素排列顺序
public void testOrder(Set set) {
set.add("b");
set.add("a");
set.add("c");
System.out.println(set.getClass().getName() +"的成员顺序是: " + set);
}
public static void main(String[] args) {
SetTest st = new SetTest();
st.testOrder(new HashSet());
st.testOrder(new LinkedHashSet());
st.testOrder(new TreeSet());
st.testRebundant(new HashSet());
st.testRebundant(new LinkedHashSet());
st.testRebundant(new TreeSet());
}
}
运行结果:
(3)迭代器
迭代器是一种常用的模式,习惯上称之为“迭代器模式”或“Iterator模式”。该模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。
如果没有使用迭代器模式,我们如果想要遍历一个ArrayList代码只能用下面的实现
for (int i = 0; i < list.size(); i ++){
list.get(i);
}
这种方法程序员必须事先知道几何的内部结构,访问代码和集合本身是紧耦合,无法将访问逻辑从集合类和客户端代码中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。而且如果想要遍历Set类型的集合,java类库中并没有提供合适的方法,更糟的是假设程序员在程序运行一段时间后发现需要一个不能有重复成员的集合,此时将List更改成Set完全无法工作,因为Set接口没有get方法。
而Iterator模式则规定对所有的集合采用同一种方式遍历成员,在Java类库中,所有实现Collection接口的类都可以通过方法iterator()获取一个能够遍历其所有成员的迭代器,因此,上面的例子改成下面的代码后,如果想要更改List接口为Set接口将是轻而易举的事情;
Iteator iter = list.iterator();
while (iter.hasNext()){
iter.next();
}
转变成Set接口只要修改一处代码即可
Iteator iter = set.iterator();
while (iter.hasNext()){
iter.next();
}
所有类型集合生成的迭代器都必须实现Iterator接口,但是其实现方式可以完全不一样,只要实现了Iterator接口以下三个方法就可以了;
boolean hashNext();
Object next();
void remove();
下面代码自己来设计一个支持迭代器的容器:
import java.util.*;
public class IterableClass implements Iterable<String>
{
protected String[] words=("And that is how "+"we know the earth to be banana-shaped").split(" ");
public Iterator<String> iterator()
{
return new Iterator<String>()
{
private int index=0;
public boolean hasNext()
{
return index < words.length;
}
public String next(){ return words[index++]; }
public void remove()
{ throw new UnsupportedOperationException(); }
};
}
public static void main(String[] args)
{
for(String s: new IterableClass())
System.out.print(s+" ");
}
}
运行结果:
三、编程题
(1)教材279页编程题第1题;
(2)教材280页编程题第2题;
(3)教材280页编程题第3题。
(4)(选做题)写一个彩票程序:30选7。随机(1~30之间)生成7个随机数,注意不能重复。然后从键盘输入7个数,对比7个数是否与随机数有相同的。最后显示“中了几个号”。同时,如果中了7个号,显示一等奖;如果中了6个号,显示二等奖;如果中了5个号,显示三等奖。要求:选用合适的容器和算法。(说明:键盘输入可以使用Scanner类)
四、实验结果
(1)程序1运行结果
(2)程序2运行结果
(3)程序3运行结果
(4)程序4运行结果(如选做)
五、实验源代码
(1)程序1源代码
package test6;
import java.util.*;
public class Example1 {
public static void main(String[] args) {
ArrayList list = new ArrayList(); // 创建ArrayList集合
list.add("stu1"); // 向该集合添加元素
list.add("stu2");
list.add("stu3");
list.add("stu4");
list.add("stu5"); // 向该集合添加元素
list.add("stu6");
list.add("stu7");
list.add("stu8");
list.add("stu9"); // 向该集合添加元素
list.add("stu0");
Iterator it = list.iterator(); // 获取Iterator对象
while (it.hasNext()) { // 判断ArrayList集合中是否存在下一个元素
Object obj = it.next(); // 取出ArrayList集合中的元素
System.out.print(obj+" ");
}
}
}
(2)程序2源代码
package test6;
import java.util.*;
class Person {
private String age;
private String name;
public Person(String age, String name) {
this.age = age;
this.name = name;
}
// 重写toString()方法
public String toString() {
return name + "," + age;
}
// 重写hashCode方法
public int hashCode() {
return name.hashCode(); // 返回id属性的哈希值
}
// 重写equals方法
public boolean equals(Object obj) {
if (this == obj) { // 判断是否是同一个对象
return true; // 如果是,直接返回true
}
if (!(obj instanceof Person)) { // 判断对象是为Student类型
return false; // 如果对象不是Student类型,返回false
}
Person p = (Person) obj; // 将对象强转为Student类型
boolean b = this.name.equals(p.name); // 判断id值是否相同
return b; // 返回判断结果
}
}
public class Example2 {
public static void main(String[] args) {
HashSet hs = new HashSet(); // 创建HashSet对象
Person p1 = new Person("18", "Jack"); // 创建Student对象
Person p2 = new Person("19", "Rose");
Person p3 = new Person("20", "Rose");
hs.add(p1); // 向集合存入对象
hs.add(p2);
hs.add(p3);
System.out.println(hs); // 打印集合中的元素
}
}
(3)程序3源代码
package test6;
import java.util.*;
public class Example3 { // 创建TreeMap测试类
public static void main(String[] args) {
TreeMap tm = new TreeMap();// 传入一个自定义比较器
tm.put("1", "Jack"); // 向集合存入学生的学号和姓名
tm.put("2", "Rose");
tm.put("5", "Lucy");
tm.put("3", "Lucy");
tm.put("4", "Rose");
Set keySet = tm.keySet(); // 获取键的集合
Iterator it = keySet.iterator(); // 获得迭代器对象
while (it.hasNext()) {
Object key = it.next(); // 获得一个键
Object value = tm.get(key); // 获得键对应的值
System.out.println(key + ":" + value);
}
}
}
(4)程序4源代码(如选做)
package test6;
import java.io.IOException;
import java.util.*;
public class Example4 {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
// 随机生成7个不重复的数
int[] r = new int[7];
boolean[] b = new boolean[31]; // 记录该数是否已经生成
for (int i = 0; i < 7; i++) {
int tem = (int) (Math.random() * 30) + 1;
while (b[tem] == true)
tem = (int) (Math.random() * 30) + 1;
r[i] = tem;
b[tem] = true;
}
// 输入7个数
System.out.println("Please enter your numbers:");
int[] in = new int[7];
for (int i = 0; i < 7; i++) {
in[i] = scanner.nextInt();
}
// 打印生成的7个随机数
System.out.println("Random numbers:");
for (int i = 0; i < 7; i++) {
System.out.print(r[i] + " ");
}
System.out.println();
// 打印你输入的7个数
System.out.println("Your numbers:");
for (int i = 0; i < 7; i++) {
System.out.print(in[i] + " ");
}
System.out.println();
// 打印相同的数
int count = 0;
System.out.println("The same numbers:");
for (int i = 0; i < 7; i++)
for (int j = 0; j < 7; j++) {
if (in[i] == r[j]) {
System.out.println(in[i] + " ");
count++;
}
}
switch (count) {
case 1:
case 2:
case 3:
case 4:
System.out.println("Thanks!");
break;
case 5:
System.out.println("Third prize!");
break;
case 6:
System.out.println("Second prize!");
break;
case 7:
System.out.println("First prize!");
break;
}
System.out.println();
}
}