集合 Collection 和 List、Set、Map 之间的关系如下图所示:
其中,ArrayList、HashSet 和 HashMap 为常用类。
集合相比数组的优势:
1. 数组长度固定,而集合长度可变。
2. 数组只能通过下标访问元素,类型固定,而有的集合可以通过任意类型查找所映射的具体对象。
1. List
List 是元素 有序 且 可重复 的集合,称为 序列。
List 可以精确控制每个元素的插入位置,或删除某个位置的元素。
ArrayList:数组序列,List 接口的一个重要实现类,ArrayList 底层是由数组来实现的。
下面以学生课程管理为例,介绍 List 的用法。
首先新建一个课程类,包含课程编号和课程名,代码如下:
public class Course {
private String id;
private String name;
public Course(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1.1 向 List 中添加元素
创建一个类,名为 ListTest,用 add() 方法添加一个项目。
示例代码:
public class ListTest {
// 用于存放待选课程的 List
public List<Course> coursesForSelect;
public ListTest() {
this.coursesForSelect = new ArrayList<Course>();// 注意 List 是接口,不能实例化
}
// 测试 add 方法
public void testAdd() {
// add方法一
Course c1 = new Course("1", "数据结构");
coursesForSelect.add(c1);// 添加到第0个位置,若再用此方法,则依次向后排列
// add方法二(添加到指定位置)
Course c2 = new Course("2", "C语言");
coursesForSelect.add(0, c2);// 添加到第0个位置,把原先第0个位置的挤到第1个
// 注意:若添加位置大于 List 长度,则会抛出异常 IndexOutOfBoundsException
// Course c3 = new Course("3", "test");
// coursesForSelect.add(3, c3);
}
}
添加多个项目,addAll() 方法。
示例代码:
public void testAdd() {
// addAll方法一
Course[] c4 = {new Course("3", "汇编语言"), new Course("4","Java")};
coursesForSelect.addAll(Arrays.asList(c4));
// addAll方法二,添加到指定位置
Course[] c5 = {new Course("5", "高等数学"), new Course("6","概率论")};
coursesForSelect.addAll(2, Arrays.asList(c5));
// 下面几句仅供测试添加效果
Course t5 = coursesForSelect.get(2);
Course t6 = coursesForSelect.get(3);
System.out.println("添加了课程:" + t5.getId() + "." + t5.getName());
System.out.println("添加了课程:" + t6.getId() + "." + t6.getName());
}
1.2 获取 List 的元素
获取 List 中的元素,有三种方法。
1、用 get() 方法,示例代码:
public void testGet() {
int size = coursesForSelect.size();// 获取数组长度
System.out.println("有以下待选课程:");
for (int i=0; i<size; i++) {
Course c = coursesForSelect.get(i);
System.out.println("课程:" + c.getId() + "." + c.getName());
}
}
2、 用迭代器 Iterator,示例代码:
public void testIterator() {
Iterator<Course> it = coursesForSelect.iterator();
System.out.println("有以下待选课程:");
while(it.hasNext()) {
Course c = it.next();
System.out.println("课程:" + c.getId() + "." + c.getName());
}
}
3、 foreach 方法(即增强的 for 循环),示例代码:
public void testForeach() {
System.out.println("有以下待选课程:");
for(Course c : coursesForSelect) {
System.out.println("课程:" + c.getId() + "." + c.getName());
}
}
1.3 修改 List 的元素
set() 方法,示例代码:
public void testModify() {
coursesForSelect.set(2, new Course("7","大学历史"));
}
1.4 删除 List 的元素
删除 List 中的元素有两种方法:remove() 和 removeAll()。
PS: 类似 add 和 addAll 方法。
删除某个元素:remove方法
public void testRemove() {
// 删除某个元素:remove方法
Course c = coursesForSelect.get(3);
coursesForSelect.remove(c);// 删除第三个元素
testForeach();// 显示所有课程(测试删除后的效果)
}
删除多个元素:removeAll方法
public void testRemove() {
Course[] cc = {coursesForSelect.get(0), coursesForSelect.get(1)};
coursesForSelect.removeAll(Arrays.asList(cc));// 删除第0和第1个元素
testForeach();// 显示所有课程(测试删除后的效果)
}
2. Set
Set 是元素 无序 且 不重复 的集合,称为 集。
HashSet:哈希集,Set接口 的一个重要实现类。
小例子
功能:运行该程序后,控制台显示课程 ID 及课程名字,提示输入课程 ID 来选课。
创建一个学生类,
public class Student {
private String id;
private String name;
public Set<Course> courses;
public Student(String id, String name) {
this.id = id;
this.name = name;
this.courses = new HashSet<Course>();// 这里是 HashSet
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建一个 SetTest 类(add 方法同 ListTest),
public class SetTest {
public List<Course> coursesForSelect;
public SetTest() {
this.coursesForSelect = new ArrayList<Course>();
}
public void testAdd() {
// add方法一
Course c1 = new Course("1", "数据结构");
coursesForSelect.add(c1);
// add方法二(添加到指定位置)
Course c2 = new Course("2", "C语言");
coursesForSelect.add(0, c2);// 添加到第0个位置,把原先第0个位置的挤到第1个
// addAll方法一(添加多个项目)
Course[] c4 = {new Course("3", "汇编语言"), new Course("4","Java")};
coursesForSelect.addAll(Arrays.asList(c4));
// addAll方法二,添加(多个项目)到指定位置
Course[] c5 = {new Course("5", "高等数学"), new Course("6","概率论")};
coursesForSelect.addAll(2, Arrays.asList(c5));
}
/**
* 通过for each(即增强for循环)访问集合元素
*/
public void testForeach() {
System.out.println("有以下待选课程:");
for(Course c : coursesForSelect) {
System.out.println("课程:" + c.getId() + "." + c.getName());
}
}
public void p(Student st) {
// 循环遍历输出学生所选课程
for (Course c : st.courses) {
System.out.println("选择了课程:" + c.getId() + "." + c.getName());
}
}
public static void main(String[] args) {
SetTest st = new SetTest();
st.testAdd();
st.testForeach();
// 创建一个学生对象
Student s = new Student("1", "小明");
System.out.println("欢迎" + s.getName() + "选课!");
// 创建一个Scanner对象,用来接收从键盘输入的课程ID
Scanner console = new Scanner(System.in);
for (int i=0; i<3; i++) {
System.out.println("请输入课程ID:");
String courseId = console.next();
for (Course c : st.coursesForSelect) {
if (c.getId().equals(courseId)) {
s.courses.add(c);
//s.courses.add(null);// OK,但无实际意义
//s.courses.add(c);// Set中的元素是不重复的,即使多次添加最后也只保留一个该对象的引用,因此加不加本句无影响
}
}
}
st.p(s);
System.out.println();
}
}
该程序运行后,控制台输出:
输入1,2,3(序号可在给定范围自由选择,此处仅示例) 后控制台输出:
Set 是无序的,因而每次输出顺序可能和输入有不同。
Q: 为嘛我实验的总是相同??
注意:由于 Set 无序,因此循环遍历 Set 中的元素只能用 foreach 方法或 Iterator 方法,而不能使用 get 方法。
3. Map
Map 接口提供了一种映射关系,其中的关系是以 键-值对 (key-value)的形式存储的,能够根据 key 快速查找 value。
Map 中的键值对以 Entry 类型的对象实例形式存在,如图所示:
Map 中的 key 不能重复,value 可重复。
3.1 向 Map 添加映射
添加元素: put 方法。
小例子:
新建 MapTest 类,添加学生ID,判断是否被占用,若未被占用,则输入姓名,创建新学生对象,并且添加到students中
public class MapTest {
/**
* 装学生对象
*/
public Map<String, Student>students;
/**
* 构造方法中初始化students
*/
public MapTest() {
this.students = new HashMap<String, Student>();
}
public void testPut() {
// 创建一个Scanner对象,获取键盘输入的学生ID和姓名
Scanner console = new Scanner(System.in);
int i=0;
while(i<3) {
System.out.println("请输入学生ID:");
String id = console.next();
// 判断ID是否被占用
Student s = students.get(id);
if (s == null) {
// 提示输入学生姓名
System.out.println("请输入学生姓名:");
String name = console.next();
Student newS = new Student(id, name);
students.put(id, newS);// 通过调用 students 的 put 方法添加 ID-Student 映射
System.out.println("成功添加学生:" + newS.getId() + "." + newS.getName());
i ++;
} else {
System.out.println("该学生ID已被占用!");
continue;// 让循环继续
}
}
}
}
3.2 删除 Map 中的映射
使用 remove 方法(只删除 key 即可),
public void testRemove() {
// 提示要删除的学生ID
System.out.println("请输入要删除的学生ID:");
// 获取从键盘输入的待删除的学生ID字符串
Scanner console = new Scanner(System.in);
while(true) {
String id = console.next();
// 判断该ID是否有对应的学生对象
Student s = students.get(id);
if (s == null) {
System.out.println("该ID不存在!");
continue;// 让循环继续进行
}
students.remove(id);
System.out.println("成功删除学生:" + s.getName());
break;// 退出循环
}
}
3.3 修改 Map 中的映射
也用 put 方法实现,
public void testModify() {
// 提示要修改的学生ID
System.out.println("请输入要修改的学生ID:");
// 创建一个Scanner对象,去获取键盘上输入的学生ID字符串
Scanner console = new Scanner(System.in);
while(true) {
// 取得从键盘输入的学生ID
String sID = console.next();
// 从students中查找该学生ID对应的学生对象
Student s = students.get(sID);
if (s == null) {
System.out.println("该ID不存在,请重新输入!");
continue;
}
// 提示当前对应的学生对象的姓名
System.out.println("当前该学生ID,所对应的学生为:" + s.getName());
// 提示输入新的学生姓名,修改
System.out.println("请输入新的学生姓名:");
String name = console.next();
Student newS = new Student(sID, name);
students.put(sID, newS);
System.out.println("修改成功!");
break;
}
}
3.4 遍历 Map 中的元素
3.4.1 keySet 方法
keySet 方法,返回 Map 中所有 键 的集合。
public void testKeySet() {
// 通过keySet方法,返回 Map 中的所有‘键’的Set集合
Set<String> keySet = students.keySet();
// 取得students的容量
System.out.println("总共有 " + students.size() + " 个学生!");
// 遍历 keySet,取得每一个键,再调用get方法取得每个键对应的value
for (String sId : keySet) {
Student s = students.get(sId);
if(s != null) {
System.out.println("学生:" + s.getName());
}
}
}
3.4.2 entrySet 方法
entrySet 方法:返回 键-值对 的集合。
public void testEntrySet() {
// 通过entrySet方法,返回Map中所有键值对
Set<Entry<String,Student>> entrySet = students.entrySet();// 注意:Entry也是有泛型的<String,Student>
for (Entry<String, Student> entry : entrySet) {
System.out.println("取得键:" + entry.getKey());
System.out.println("取得值:" + entry.getValue().getName());// getValue返回值类型和泛型value类型一致,因此可直接调用getName
}
}
3.4.3 values 方法
values 方法:返回 值 的集合。
示例代码:
Collection c = map.values();
Iterator iterator = c.iterator();
while(iterator.hasNext()) {
System.out.println("value:"+ iterator.next());
}
PS: 主要内容整理总结自 慕课网