一、 选择题
1. 以下选项中关于Java集合的说法错误的是(AC)。
A.List接口和Set接口是Collections接口的两个子接口
B.List接口中存放的元素具有有序,不唯一的特点
C.Set接口中存放的元素具有无序,不唯一的特点
D.Map接口存放的是映射信息,每个元素都是一个键值对
A中是Collection接口
C中Set接口存放的元素是无序但唯一的
2. 如下Java代码,输出的运行结果是(A)。
public class Test {
public static void main(String[ ] args) {
List<String> list=new ArrayList<String>();
list.add("str1");
list.add(2, "str2");
String s=list.get(1);
System.out.println(s);
}
}
A.运行时出现异常
B.正确运行,输出str1
C.正确运行,输出str2
D.编译时出现异常
Exception in thread “main” java.lang.IndexOutOfBoundsException:
3. 在Java中,下列集合类型可以存储无序、不重复的数据的是(D)。
A.ArrayList
B.LinkedList
C.TreeSet
D.HashSet
TreeSet内部需要对存储的元素进行排序
4. 以下代码的执行结果是(C )。
Set<String> s=new HashSet<String>();
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
5. 给定如下Java代码,编译运行的结果是( C)。(选择一项)
public class Test {
public static void main(String[] args) {
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
键值对中key唯一,如果重复则新的覆盖旧的
二、 简答题
1. 集合和数组的比较。
-
数组特点:大小固定,只能存储相同数据类型的数据
-
集合特点:大小可动态扩展,可以存储各种类型的数据
2. 简述List、Set、Collection、Map的区别和联系。
- Collection 是一个接口,Collection接口的两个子接口是List、Set接口。
- List 中的元素有顺序,可重复。
- Set 中的元素没有顺序,不可重复。
- Map 中存储的“键值对”通过键来标识,所以“键对象”不能重复。
3. ArrayList和LinkedList的区别和联系。它们的底层分别是用什么实现的?
- ArrayList底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。
- LinkedList底层用双向链表实现的存储。特点:查询效率低,增删效率高,线程不安全。
4. HashSet采用了哈希表作为存储结构,请说明哈希表的特点和实现原理
提示:结合Object类的hashCode()和equals()说明其原理。
哈希表的本质就是“数组+链表”,结合了两者的优点,查询快,增删效率也高
hashCode()方法用来计算key的哈希值,equals()方法用来判断两个键值对中的key是否相等。
存储数据过程put(key,value)
哈希表的本质就是“数组+链表”
- 第一步:获得key对象的hashcode
- 第二步:根据hashcode计算出hash值(要求在[0, 数组长度-1]区间)
- 第三步:生成Entry对象,一个Entry对象包含4部分:key对象、value对象、hash值、指向下一个Entry对象的引用。
- 第四步:将Entry对象放到table数组中
当添加一个元素(key-value)时,首先计算key的hash值,以此确定插入数组中的位置,但是可能存在同一hash值的元素已经被放在数组同一位置了,这时就添加到同一hash值的元素的后面,他们在数组的同一位置,就形成了链表,同一个链表上的Hash值是相同的,所以说数组存放的是链表。 JDK8中,当链表长度大于8时,链表就转换为红黑树,这样又大大提高了查找的效率。
取数据过程get(key)
(1) 获得key的hashcode,通过hash()散列算法得到hash值,进而定位到数组的位置。
(2) 在链表上挨个比较key对象。 调用equals()方法,将key对象和链表上所有节点的key对象进行比较,直到碰到返回true的节点对象为止。
(3) 返回equals()为true的节点对象的value对象。
5. 使用泛型有什么好处?
-
向集合添加数据时保证数据安全。
-
遍历集合元素时不需要强制转换。
三、 编码题
1. 使用List和Map存放多个图书信息,遍历并输出。其中商品属性:编号,名称,单价,出版社;使用商品编号作为Map中的key。
package HomeWork9;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class hw1 {
public static void main(String[] args) {
Book book1 = new Book(1001, "数据结构与算法", 55, "上海大学出版社");
Book book2 = new Book(1002, "操作系统", 80, "苏州大学出版社");
Book book3 = new Book(1003, "Java程序设计", 66, "北京大学出版社");
Book book4 = new Book(1004, "鸟哥的Linux私房菜", 100, "南京大学出版社");
List<Book> list = new ArrayList<Book>();
list.add(book1);
list.add(book2);
list.add(book3);
list.add(book4);
for (Book book : list) {
System.out.println(book);
}
System.out.println("----------------------------------------");
Map<Integer, Book> map = new HashMap<Integer, Book>();
map.put(book1.getId(), book1);
map.put(book2.getId(), book2);
map.put(book3.getId(), book3);
map.put(book4.getId(), book4);
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
System.out.println(key + ":" + map.get(key));
}
}
}
class Book {
private int id;
private String name;
private int price;
private String press;
public Book() {
// TODO Auto-generated constructor stub
}
public Book(int id, String name, int 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 int getPrice() {
return price;
}
public void setPrice(int 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 + ", price=" + price + ", press=" + press + "]";
}
}
2. 使用HashSet和TreeSet存储多个商品信息,遍历并输出;其中商品属性:编号,名称,单价,出版社;要求向其中添加多个相同的商品,验证集合中元素的唯一性。
提示:向HashSet中添加自定义类的对象信息,需要重写hashCode和equals( )。
向TreeSet中添加自定义类的对象信息,需要实现Comparable接口,指定比较规则。
package HomeWork9;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class hw2 {
public static void main(String[] args) {
// 使用HashSet存储
Set<Goods> set1 = new HashSet<Goods>();
set1.add(new Goods(1001, "数据结构与算法", 55, "上海大学出版社"));
set1.add(new Goods(1002, "操作系统", 80, "苏州大学出版社"));
set1.add(new Goods(1003, "Java程序设计", 66, "北京大学出版社"));
set1.add(new Goods(1004, "鸟哥的Linux私房菜", 100, "南京大学出版社"));
set1.add(new Goods(1001, "数据结构与算法", 55, "上海大学出版社"));
set1.add(new Goods(1004, "鸟哥的Linux私房菜", 100, "南京大学出版社"));
for (Goods goods : set1) {
System.out.println(goods);
}
System.out.println("------------------------------");
// 使用TreeSet存储
Set<Goods> set2 = new TreeSet<Goods>();
set2.add(new Goods(1001, "数据结构与算法", 55, "上海大学出版社"));
set2.add(new Goods(1002, "操作系统", 80, "苏州大学出版社"));
set2.add(new Goods(1003, "Java程序设计", 66, "北京大学出版社"));
set2.add(new Goods(1004, "鸟哥的Linux私房菜", 100, "南京大学出版社"));
set2.add(new Goods(1001, "数据结构与算法", 55, "上海大学出版社"));
set2.add(new Goods(1004, "鸟哥的Linux私房菜", 100, "南京大学出版社"));
for (Goods goods : set2) {
System.out.println(goods);
}
}
}
class Goods implements Comparable<Goods> {
// 编号,名称,单价,出版社
private int id;
private String name;
private int price;
private String press;
public Goods() {
// TODO Auto-generated constructor stub
}
public Goods(int id, String name, int 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 int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
@Override
public String toString() {
return "Goods [id=" + id + ", name=" + name + ", price=" + price + ", press=" + press + "]";
}
@Override
public int compareTo(Goods o) {
if (this.id > o.id) {
return 1;
} else {
return 0;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Goods other = (Goods) obj;
if (id != other.id)
return false;
return true;
}
}
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接口的作用,并通过分数来对学生进行排序。
package HomeWork9;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
public class hw3 {
public static void main(String[] args) {
hw3 homework = new hw3();
homework.listToMap();
System.out.println("------------------------------------------");
homework.mapToList();
System.out.println("------------------------------------------");
homework.sortGrade();
}
public void listToMap() { // 将List中Student元素封装到Map中
// 创建学生信息
Student stu1 = new Student(1001, "张三", 21, "男", 66);
Student stu2 = new Student(1002, "李四", 22, "男", 85);
Student stu3 = new Student(1003, "王五", 23, "男", 72);
Student stu4 = new Student(1004, "蔡蔡", 24, "女", 100);
// 加入List中
List<Student> list1 = new ArrayList<Student>();
list1.add(stu1);
list1.add(stu2);
list1.add(stu3);
list1.add(stu4);
// 遍历输出每个student信息
System.out.println("每个学生信息为:");
for (Student student : list1) {
System.out.println(student);
}
System.out.println("------------------------------------------");
// 将List中数据放入Map,使用Student的id属性作为key
// 使用迭代器
Map<Integer, Student> map1 = new HashMap<Integer, Student>();
Iterator<Student> iter = list1.iterator();
while (iter.hasNext()) {
Student stu = iter.next();
map1.put(stu.getId(), stu);
}
// 遍历Map,输出每个节点的Key和Value
Set<Entry<Integer, Student>> entrySet = map1.entrySet();
System.out.println("List-->Map");
for (Entry<Integer, Student> entry : entrySet) {
System.out.println(entry.getKey() + "--->" + entry.getValue());
}
}
public void mapToList() { // 将Map中Student映射信息封装到List
// 创建学生信息
Student stu1 = new Student(1001, "张三", 21, "男", 66);
Student stu2 = new Student(1002, "李四", 22, "男", 85);
Student stu3 = new Student(1003, "王五", 23, "男", 72);
Student stu4 = new Student(1004, "蔡蔡", 24, "女", 100);
// 将学生id作为Map集合的Key,学生对象作为Map集合的Value
Map<Integer, Student> map2 = new HashMap<>();
map2.put(stu1.getId(), stu1);
map2.put(stu2.getId(), stu2);
map2.put(stu3.getId(), stu3);
map2.put(stu4.getId(), stu4);
// 将Map中的信息放入List对象
List<Student> list2 = new ArrayList<>();
Set<Entry<Integer, Student>> setEntry = map2.entrySet();
for (Entry<Integer, Student> entry : setEntry) {
list2.add(entry.getValue());
}
// 遍历List集合
Iterator<Student> iter = list2.iterator();
System.out.println("Map-->List");
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
public void sortGrade() {
// 创建学生信息
Student stu1 = new Student(1001, "张三", 21, "男", 66);
Student stu2 = new Student(1002, "李四", 22, "男", 85);
Student stu3 = new Student(1003, "王五", 23, "男", 72);
Student stu4 = new Student(1004, "蔡蔡", 24, "女", 100);
System.out.println("使用TreeSet对分数进行排序");
// 使用TreeMap
Set<Student> set3 = new TreeSet<>();
set3.add(stu1);
set3.add(stu2);
set3.add(stu3);
set3.add(stu4);
for (Student stu : set3) {
System.out.println(stu);
}
}
}
Student类:
package HomeWork9;
public class Student implements Comparable<Student> {
private int id;
private String name;
private int age;
private String sex;
private int grade;
public Student() {
// TODO Auto-generated constructor stub
}
public Student(int id, String name, int age, String sex, int grade) {
super();
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.grade = grade;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.id = grade;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", grade=" + grade + "]";
}
@Override
public int compareTo(Student o) {
if (this.grade > o.grade) {
return 1;
} else if (this.grade < o.grade) {
return -1;
} else {
if (this.id > o.id) {
return 1;
} else if (this.id < o.id) {
return -1;
} else {
return 0;
}
}
}
}
每个学生信息为:
Student [id=1001, name=张三, age=21, sex=男, grade=66]
Student [id=1002, name=李四, age=22, sex=男, grade=85]
Student [id=1003, name=王五, age=23, sex=男, grade=72]
Student [id=1004, name=蔡蔡, age=24, sex=女, grade=100]
------------------------------------------
List-->Map
1001--->Student [id=1001, name=张三, age=21, sex=男, grade=66]
1002--->Student [id=1002, name=李四, age=22, sex=男, grade=85]
1003--->Student [id=1003, name=王五, age=23, sex=男, grade=72]
1004--->Student [id=1004, name=蔡蔡, age=24, sex=女, grade=100]
------------------------------------------
Map-->List
Student [id=1001, name=张三, age=21, sex=男, grade=66]
Student [id=1002, name=李四, age=22, sex=男, grade=85]
Student [id=1003, name=王五, age=23, sex=男, grade=72]
Student [id=1004, name=蔡蔡, age=24, sex=女, grade=100]
------------------------------------------
使用TreeSet对分数进行排序
Student [id=1001, name=张三, age=21, sex=男, grade=66]
Student [id=1003, name=王五, age=23, sex=男, grade=72]
Student [id=1002, name=李四, age=22, sex=男, grade=85]
Student [id=1004, name=蔡蔡, age=24, sex=女, grade=100]