容器作业
一、填空题
1.Java集合框架提供了一套性能优良、使用方便的接口和类,包括Collection和Map两大类,它们都位于 java.util 包中
2.队列和堆栈有些相似,不同之处在于 。
3. 结构是一种由多个节点组成的线性数据结构,并且每个节点包含有数据以及指向下一个节点的引用。
4.__是一种集合类,它 采用链表作为的存储结构,便于删除和添加元素,但是按照索引查询元素效率低下。
5. 是一种Collection类型的集合类,其中元素唯一,并采用二叉树作为存储结构,元素按照自然顺序排列。
6.如果希望将自定义类Student的多个对象放入集合TreeSet,实现所有元素按照某个属性的自然顺序排列,则需要Student类实现__________________接口。
7.在Java中 集合的访问时间接近稳定,它是一种键值对映射的数据结构。这个数据结构是通过数组来实现的。
8.迭代器Iterator为集合而生,专门实现集合遍历,该接口有三个方法,分别是hasNext() 、、remove()。

二、选择题

以下选项中关于Java集合的说法错误的是( )。(选择二项)

A. List接口和Set接口是Collections接口有两个子接口
B. List接口中存放的元素具有有序,不唯一的特点
C. Set接口中存放的元素具有无序,不唯一的特点
D. Map接口存放的是映射信息,每个元素都是一个键值对

如下Java代码,输出的运行结果是( )。(选择一项)

public class Test {undefined
 public static void main(String[ ] args) {undefined
 List list=new ArrayList();
 list.add(“str1”);
 list.add(2, “str2”);
 String s=list.get(1);
 System.out.println(s);
 }
 }

A 运行时出现异常
B. 正确运行,输出str1
C. 正确运行,输出str2
D. 编译时出现异常

以下Java代码的作用是首先将一个数组的内容存入集合,然后判断集合中是否有指定的元素存在,其中共有( )处错误。(选择一项)

import java.util.List;
 public class Test {undefined
 public int getIndexofArray(float[] f){undefined
 int rtn=-1;
 float objf=3.4;
 List list=null;
 for(int i=0;i<f.size( );i++){undefined
 list.add(f[i]);
 }
 for(int i=0;i<list.size( );i++){undefined
 float tmp=(float)list.get(i);
 if(objf==tmp){undefined
 rtn=i;
 }
 }
 return rtn;
 }
 }

A 0
B. 1
C. 2
D. 3

分析如下Java 代码,编译运行后将输出( )。(选择一项)

public class Test {undefined
 public Test() {undefined
 }
 static void print(List al) {undefined
 al.add(2);
 al = new ArrayList();
 al.add(3);
 al.add(4);
 }
 public static void main(String[] args) {undefined
 List al = new ArrayList();
 al.add(1);
 print(al);
 System.out.println(al.get(1));
 }
 }

A 1
B. 2
C. 3
D. 4

在Java中,下列集合类型可以存储无序、不重复的数据的是( )。(选择一项)

A ArrayList
B. LinkedList
C. TreeSet
D. HashSet

以下代码的执行结果是( )。(选择一项)
Set s=new HashSet();
s.add(“abc”);
s.add(“abc”);
s.add(“abcd”);
s.add(“ABC”);
System.out.println(s.size());

A. 1
B. 2
C. 3
D. 4

给定如下Java代码,编译运行的结果是( )。(选择一项)

public class Test {undefined
 public static void main(String[] args) {undefined
 Map<String, String> map = new HashMap<String, String>();
 String s = “code”;
 map.put(s, “1”);
 map.put(s, “2”);
 System.out.println(map.size());
 }
 }

A 编译时发生错误
B. 运行时引发异常
C. 正确运行,输出:1
D. 正确运行,输出:2

下面集合类中属于非线程安全,且结构采用了哈希表的是( )。(选择一项)

A. Vector
B. ArrayList
C. HashMap
D. Hashtable

在Java中,LinkedList类与ArrayList类同属于集合框架类,下列( )选项中是LinkedList类有而ArrayList类没有的方法。(选择两项)

A    add(Object o)
B.    add(int index,Object o)
C.    getFirst()
D.    removeLast()
1
2
3
4
三、判断题
1.数组和集合中的元素可以是任何数据类型,包括基本类型和引用类型。( )
2.容器指的是“可以容纳其他对象的对象”。( )
3.Java集合中的Set接口和List接口都是从Collection接口派生出来的。( )
4.Collection 接口存储一组不唯一,有序的对象,它有两个子接口:List和Set。( )
5.Collection是Java集合顶级接口,其中的元素无序,唯一。Java平台不提供这个接口任何直接的实现。( )
6.List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引来访问List中的无素,这类似于Java的数组。( )
7.HashSet采用哈希表存储结构,特点是查询速度快,但是其中元素无序排列。( )
8.LinkedHashMap是一种有序的HashMap,查询速度快,便于添加删除操作。( )
9.基本数据类型的值可以被直接存储在Vector对象中。( )
10.Dictionary建立了关键字和值的映射,只要提供一个关键字,Dictionary就会返回一个相应的值。( )
11.泛型是JavaSE1.7的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。Java语言引入泛型的好处是安全简单。( )
12.Collection是专门操作集合的工具类,提供一系列静态方法实现对各种集合操作。( )
13.Iterator接口可以遍历任何Collection接口的实现类,可以从一个Collection中使用iterator( )方法来获取迭代器实例。迭代器取代了Java集合框架中的Enumeration。( )
14.采用增强for循环遍历List或者Set,如果List或者Set没有加泛型,也能遍历。( )
15.在类已经重写equals和hashCode方法的前提下,equals返回true,hashcode一定相等。( )

四、简答题
1.集合和数组的比较
2.简述List、Set、Collection、Map的区别和联系。
3.ArrayList和LinkedList的区别和联系。它们的底层分别是用什么实现的?
4.HashSet采用了哈希表作为存储结构,请说明哈希表的特点和实现原理。
提示:结合Object类的hashCode()和equals()说明其原理
5.Vector和ArrayList的区别和联系。
6.请你简述HashMap和Hashtable的区别?
7.说明isEmpty的作用,并说明下面代码有问题吗?

Collection c = null;
System.out.println(c.isEmpty());

8.写出List、Set、Map中使用泛型的例子。
9.使用泛型有什么好处?
10.每个对象都有一个哈希码吗?哈希码是根据什么生成的?会不会重复?

五、编码题
1.使用List和Map存放多个图书信息,遍历并输出。其中商品属性:编号,名称,单价,出版社;使用商品编号作为Map中的key。
2.使用HashSet和TreeSet存储多个商品信息,遍历并输出;其中商品属性:编号,名称,单价,出版社;要求向其中添加多个相同的商品,验证集合中元素的唯一性。
提示:向HashSet中添加自定义类的对象信息,需要重写hashCode和equals( )
向TreeSet中添加自定义类的对象信息,需要实现Comparable接口,指定比较规则
3.实现List和Map数据的转换。具体要求如下:
功能1:定义方法public void listToMap( ){ }将List中Student元素封装到Map中
1)使用构造方法Student(int id,String name,int age,String sex )创建多个学生信息并加入List
2)遍历List,输出每个Student信息
3)将List中数据放入Map,使用Student的id属性作为key,使用Student对象信息作为value
4)遍历Map,输出每个Entry的key和value
功能2:定义方法public void mapToList( ){ }将Map中Student映射信息封装到List
1)创建实体类StudentEntry,可以存储Map中每个Entry的信息
2)使用构造方法Student(int id,String name,int age,String sex )创建多个学生信息,并使用Student的id属性作为key,存入Map
3)创建List对象,每个元素类型是StudentEntry
4)将Map中每个Entry信息放入List对象
功能3:说明Comparable接口的作用,并通过分数来对学生进行排序。
4.用代码写出遍历List的三种方式。
5.用代码写出遍历Set的两种方式。
6.用代码写出遍历map的方式。

六、可选题
1.假如有以下email数据“aa@sohu.com,bb@163.com,cc@sina.com,…”现需要把email中的用户部分和邮件地址部分分离,分离后以键值对应的方式放入HashMap?
2.由控制台按照固定格式输入学生信息,包括学号,姓名,年龄信息,当输入的内容为exit退出;将输入的学生信息分别封装到一个Student对象中,再将每个Student对象加入到一个集合中,要求集合中的元素按照年龄大小正序排序;最后遍历集合,将集合中学生信息写入到记事本,每个学生数据占单独一行。
推荐步骤:
a)创建Student类,并指定按照年龄正序排列
b)通过控制台输入多个不同Student信息。格式规定为:编号#姓名#年龄
c)取出字符串中相应信息放入Student对象,并将Student加入到集合中
d)遍历集合的过程中将学生的信息输入到记事本
难点:
e)如何指定学生按照年龄正序排列
f)如果从字符串“编号#姓名#年龄”中提取学生信息
g)放入哪种集合后可以保证学生按照年龄大小正序排列
h)如何将集合中学生信息写入记事本,每个学生数据占单独一行

3.针对List中新增的有关顺序的方法,如add(int index, E element) , get(int index)等每个都进行测试。并且使用debug来帮助我们理解程序运行。
4.Collection和Collections有什么区别?
5.Map中,key能否重复?如果重复,会有什么现象?
6.请你简述Set和List的特点跟区别?
7.我有一些数据,需要频繁的查询,插入和删除操作非常少,并且没有线程之间的共享,使用List下面的哪个实现类好一些?
8.我想定义一个数组。该数组既可以放:Dog对象、也可以放Cat对象、还可以放Integer对象,怎么定义?

容器作业答案
一、填空题

1.java.util
2.栈是先进后出,队列是先进先出
3.链表
4.LinkedList
5.TreeSet
6.Comparable
7.HashMap
8.next( )

二、选择题

1.AC
2.A
3.D
4.B
5.D
6.C
7.C
8.C
9.CD

三、判断题

1.×
2.√
3.√
4.×
5.×
6.√
7.√
8.√
9.×
10.√
11.×
12.×
13.√
14.√
15.√

四、简答题

答案略

五、编码题
1.使用List和Map存放多个图书信息,遍历并输出。其中商品属性:编号,名称,单价,出版社;使用商品编号作为Map中的key。

public class Book {
	public int id;
	public String name;
	public double price;
	public String press;
	public Book() {
		super();
	}
	public Book(int id, String name, double price, String press) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
		this.press = press;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public String getPress() {
		return press;
	}
	public void setPress(String press) {
		this.press = press;
	}
	@Override
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", press=" + press
				+ ", price=" + price + "]";
	}	
}
public class TestListMap {
	public static void main(String[] args) {			
		Book b1 = new Book(1000, "b1", 30.5, "glls");
		Book b1_1 = new Book(1000, "b1", 30, "glls");
		Book b2 = new Book(1000, "b2", 50, "glls");
		Book b3 = new Book(1001, "b3", 30.5, "glls");
		Book b4 = new Book(1002, "b4", 30.5, "glls");
		Book b5 = new Book(1003, "b5", 50, "glls1");
		//使用HashSet存储图书并遍历
		List<Book> bookList = new ArrayList<Book>();
		bookList.add(b1);
		bookList.add(b1);
		bookList.add(b2);
		bookList.add(b3);
		bookList.add(b4);
		bookList.add(b5);
		bookList.add(b1_1);
		System.out.println("遍历输出hashset");
		System.out.println(bookList.size());
		for(Book book:bookList){
			System.out.println(book.toString());
		}
		//使用TreeSet存储图书并遍历
		Map<Integer,Book> bookMap = new HashMap<Integer,Book>();
		bookMap.put(b1.getId(),b1);
		bookMap.put(b1.getId(),b1);
		bookMap.put(b2.getId(),b2);
		bookMap.put(b3.getId(),b3);
		bookMap.put(b4.getId(),b4);
		bookMap.put(b5.getId(),b5);
		bookMap.put(b1_1.getId(),b1_1);		
		System.out.println("遍历输出treeset");
		for(Entry<Integer, Book> entry:bookMap.entrySet()){
			System.out.println(entry.getKey()+"----------->"+entry.getValue());
		}
	}
}

2.使用HashSet和TreeSet存储多个商品信息,遍历并输出;其中商品属性:编号,名称,单价,出版社;要求向其中添加多个相同的商品,验证集合中元素的唯一性。
提示:向HashSet中添加自定义类的对象信息,需要重写hashCode和equals( )
向TreeSet中添加自定义类的对象信息,需要实现Comparable接口,指定比较规则
 

public class Book implements Comparable<Book> {
	public int id;
	public String name;
	public double price;
	public String press;
	public Book() {
		super();
	}
	public Book(int id, String name, double price, String press) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
		this.press = press;
	}
	public int compareTo(Book o) {
		return this.id-o.id;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((press == null) ? 0 : press.hashCode());
		long temp;
		temp = Double.doubleToLongBits(price);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Book other = (Book) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (press == null) {
			if (other.press != null)
				return false;
		} else if (!press.equals(other.press))
			return false;
		if (Double.doubleToLongBits(price) != Double
				.doubleToLongBits(other.price))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", press=" + press
				+ ", price=" + price + "]";
	}	
}

public class TestSet {
	public static void main(String[] args) {			
		Book b1 = new Book(1000, "b1", 30.5, "glls");
		Book b1_1 = new Book(1000, "b1", 30, "glls");
		Book b2 = new Book(1000, "b2", 50, "glls");
		Book b3 = new Book(1001, "b3", 30.5, "glls");
		Book b4 = new Book(1002, "b4", 30.5, "glls");
		Book b5 = new Book(1003, "b5", 50, "glls1");
		//使用HashSet存储图书并遍历
		Set<Book> hashSet = new HashSet<Book>();
		hashSet.add(b1);
		hashSet.add(b1);
		hashSet.add(b2);
		hashSet.add(b3);
		hashSet.add(b4);
		hashSet.add(b5);
		hashSet.add(b1_1);
		System.out.println("遍历输出hashset");
		System.out.println(hashSet.size());
		for(Book book:hashSet){
			System.out.println(book.toString());
		}
		//使用TreeSet存储图书并遍历
		Set<Book> treeSet = new TreeSet<Book>();
		treeSet.add(b1);
		treeSet.add(b1);
		treeSet.add(b2);
		treeSet.add(b3);
		treeSet.add(b4);
		treeSet.add(b5);
		treeSet.add(b1_1);		
		System.out.println("遍历输出treeset");
		for(Book book:treeSet){
			System.out.println(book.toString());
		}
	}
}

3.实现List和Map数据的转换。具体要求如下:
功能1:定义方法public void listToMap( ){ }将List中Student元素封装到Map中
1)使用构造方法Student(int id,String name,int age,String sex )创建多个学生信息并加入List
2)遍历List,输出每个Student信息
3)将List中数据放入Map,使用Student的id属性作为key,使用Student对象信息作为value
4)遍历Map,输出每个Entry的key和value
 

```java
public class TestListToMap {
	public void listToMap () {
		//1.创建多个学生信息
		Student stu1 = new Student(110, "小明", 23, 98.0);
		Student stu2 = new Student(111, "大刚", 21, 80.5);
		Student stu3 = new Student(112, "小白", 12, 93.0);
		//2.加入List
		List<Student> list = new ArrayList<Student>();
		list.add(stu1);
		list.add(stu2);
		list.add(stu3);
		//3.遍历List,输出每个Student信息
		for(Student stu:list){
			System.out.println(stu);
		}
		//4.将List中数据放入Map,使用Student的id属性作为key					Map<Integer, Student> map = new HashMap<Integer, Student>();
		Iterator<Student> it = list.iterator();
		while(it.hasNext()){
			Student stu = it.next();
			map.put(stu.getId(), stu);
		}
		//5.遍历Map,输出每个Entry的key和value
		Set<Entry<Integer,Student>> entrySet = map.entrySet();
		for(Entry<Integer,Student> entry:entrySet){
			System.out.println(entry.getKey()+"---->"+entry.getValue());
		}
	}
}
功能2:定义方法public void mapToList( ){ }将Map中Student映射信息封装到List
1)创建实体类StudentEntry,可以存储Map中每个Entry的信息
2)使用构造方法Student(int id,String name,int age,String sex )创建多个学生信息,并使用Student的id属性作为key,存入Map
3)创建List对象,每个元素类型是StudentEntry
4)将Map中每个Entry信息放入List对象

public class StudentEntry {
	private int key;//关键字
	private Student stu;//学生
	public int getKey() {
		return key;
	}
	public void setKey(int key) {
		this.key = key;
	}
	public Student getStu() {
		return stu;
	}
	public void setStu(Student stu) {
		this.stu = stu;
	}	
}
public class TestMapToList {
	public void mapToList () {
		//1.创建多个学生信息
		Student stu1 = new Student(110, "小明", 23, 98.0);
		Student stu2 = new Student(111, "大刚", 21, 80.5);
		Student stu3 = new Student(112, "小白", 12, 93.0);
		//2.使用Student的id属性作为key,存入Map
		Map<Integer, Student> map = new HashMap<Integer, Student>();
		map.put(stu1.getId(), stu1);
		map.put(stu2.getId(), stu2);
		map.put(stu2.getId(), stu3);
		//3.创建List对象,每个元素类型是StudentEntry
		List<StudentEntry> list = new ArrayList<StudentEntry>();
		//4.将Map对象转化为List集合
		for (Entry<Integer, Student> entry : map.entrySet()) {
			StudentEntry studentEntry = new StudentEntry();
			// 将map中的一个映射关系,封装为一个studentEntry对象
			studentEntry.setKey(entry.getKey());
			studentEntry.setStu(entry.getValue());
			// 将studentEntry对象List集合
			list.add(studentEntry);
		}
		//5.遍历Map
		for (StudentEntry se : list) {
			System.out.println(se.getKey() + "\t" + se.getStu());
		}
	}
}

功能3:说明Comparable接口的作用,并通过分数来对学生进行排序。
实现Comparable接口的类需要实现compareTo方法,根据该方法可以根据具体的排序规则对容器中的对象进行排序。
public class Student implements Comparable{
	private int id;
	private String sex;
	private String name;
	private int score;
	private int age;
	
	public Student() {
	}
	public Student(int id, String sex, String name, int score, int age) {
		this.id = id;
		this.sex = sex;
		this.name = name;
		this.score = score;
		this.age = age;
	}
	public int compareTo(Object o) {
		Student s = (Student)o;
		return this.score-s.score;
	}
}

4.用代码写出遍历List的三种方式。 

```java
final int SIZE = list.size();
		for (int i = 0; i < SIZE; i++) {
			String s = list.get(i);
			System.out.print(s+" ");
		}
		System.out.println();
		for (String string : list) {
			System.out.print(string+" ");
		}
		System.out.println();
		Iterator<String> it = list.iterator();
		while(it.hasNext()){
			String s = it.next();
			System.out.print(s+" ");
		}
}

5.用代码写出遍历Set的两种方式。

a)增强for循环遍历
for (Integer integer : set) {
			System.out.print(integer.intValue() + " ");
		}
b)Iterator 遍历
Iterator<Integer> iterator = set.iterator();
	while(iterator.hasNext()){
		System.out.print(iterator.next().intValue() + " ");
}

6.用代码写出遍历map的方式。

1:得到所有的key
Set<String> set = map.keySet();
		Iterator<String> iterator = set.iterator();
		while(iterator.hasNext()){
			String key = iterator.next();
			System.out.println(key + "--->"+map.get(key));
		}
		2:得到所有的value
		Collection<String> collection = map.values();
		for (String string : collection) {
			System.out.println("value--->"+string);
		}
		3:得到所有的key和value
		Set<Entry<String, String>> entries = map.entrySet();
		Iterator<Entry<String, String>> iterator2 = entries.iterator();		
		while (iterator2.hasNext()) {
			Entry<String, String> entry = iterator2.next();
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key + "--->"+value);
	}

六、可选题
1.假如有以下email数据“aa@sohu.com,bb@163.com,cc@sina.com,…”现需要把email中的用户部分和邮件地址部分分离,分离后以键值对应的方式放入

HashMap?
public class EmailSplit {
	public static void main(String[] args) {
		String str = "aa@sohu.com,bb@163.com,cc@sina.com";
		//得到每一个email
		String strs[] = str.split(",");
		//存放分离后email的信息
		Map<String,String> emailMap = new HashMap<String, String>();
		for(String email:strs){
			String temp[] = email.split("@");
			//分割email存入map
			emailMap.put(temp[0], temp[1]);
		}
		System.out.println(emailMap.toString());
	}
}

2.由控制台按照固定格式输入学生信息,包括学号,姓名,年龄信息,当输入的内容为exit退出;将输入的学生信息分别封装到一个Student对象中,再将每个Student对象加入到一个集合中,要求集合中的元素按照年龄大小正序排序;最后遍历集合。
推荐步骤:
a)创建Student类,并指定按照年龄正序排列
b)通过控制台输入多个不同Student信息。格式规定为:编号#姓名#年龄
c)取出字符串中相应信息放入Student对象,并将Student加入到集合中
难点:
d)如何指定学生按照年龄正序排列
e)如果从字符串“编号#姓名#年龄”中提取学生信息
f)放入哪种集合后可以保证学生按照年龄大小正序排列
 

import com.shujia.wyh.day21.test.Student2;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

/*
    将集合中学生信息写入到记事本,每个学生数据占单独一行。
 */
public class Test5 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        boolean flag = true;

        //创建TreeSet集合
        TreeSet<Student2> set = new TreeSet<>(new Comparator<Student2>() {
            @Override
            public int compare(Student2 o1, Student2 o2) {
                //主要条件年龄从小到大正序排序
                int i = o1.getAge() - o2.getAge();
                //年龄一样学号不一定一样
                int i2 = i == 0 ? o1.getId() - o2.getId() : i;
                return i2;
            }
        });

        while (flag) {
            System.out.println("是否要输入学生的信息:");
            String next = sc.next();
            if ("exit".equals(next)) {
                flag = false;
            } else {
                System.out.println("请输入学生的学号:");
                int id = sc.nextInt();
                System.out.println("请输入学生的姓名:");
                String name = sc.next();
                System.out.println("请输入学生的年龄:");
                int age = sc.nextInt();

                //将输入的信息封装成一个学生对象
                Student2 student = new Student2(id, name, age);
                set.add(student);
            }
        }
        System.out.println("=========================================");

        //将集合中学生信息写入到记事本,每个学生数据占单独一行。
//        for (Student2 student2 : set) {
//            System.out.println(student2);
//        }

        BufferedWriter bw = null;
        //创建字符缓冲输出流对象
        try {
            bw = new BufferedWriter(new FileWriter("a5.txt"));
            for (Student2 student2 : set) {
                int id = student2.getId();
                String name = student2.getName();
                int age = student2.getAge();
                String s = id+","+name+","+age;
                bw.write(s);
                bw.newLine();
                bw.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}