[TOC]
*****
集合本质是基于某种数据结构数据容器。常见的数据结构:数组(Array)、集(Set)、队列(Queue)、链表(Linkedlist)、树(Tree)、堆(Heap)、栈(Stack)和映射(Map)等结构
## 20.1 集合概述
Java中提供了丰富的集合接口和类,它们来自于java.util包。如图所示
![](https://box.kancloud.cn/7440d5ba0dc2433f3e8a95bebc553401_994x485.png)
## 20.2 List集合
List集合中的元素是有序的可以重复。图20-2是一个班级集合数组,这个集合中有一些学生,这些学生是有序的,顺序是他们被放到集合中的顺序,可以通过序号访问他们。这就像老师给进入班级的人分配学号,第一个报到的是“张三”,老师给他分配的是0,第二个报到的是“李四”,老师给他分配的是1,以此类推,最后一个序号应该是“学生人数-1”。
![](https://box.kancloud.cn/ff3dc6bc9aff33330495e3337863dc00_540x684.png)
ArrayList是基于动态数组数据结构的实现,访问元素速度优于LinkedList。
LinkedList是基于链表数据结构的实现。LinkedList占用的内存空间比较大,但LinkedList在批量插入或删除数据时优于ArrayList。
### 20.2.1 常用方法
List接口继承自Collection接口,List接口中的很多方法都继承自Collection接口的。List接口中常用方法如下。
1. 操作元素
* get(int index):返回List集合中指定位置的元素。
* set(int index, Object element):用指定元素替换List集合中指定位置的元素。
* add(Object element):在List集合的尾部添加指定的元素。该方法是从Collection集合继承过来的。
* add(int index, Object element):在List集合的指定位置插入指定元素。
* remove(int index):移除List集合中指定位置的元素。
* remove(Object element):如果List集合中存在指定元素,则从List集合中移除第一次出现的指定元素。该方法是从Collection集合继承过来的。
* clear():从List集合中移除所有元素。该方法是从Collection集合继承过来的。
2. 判断集合中元素
* isEmpty():判断List集合是否为空。该方法是从Collection集合继承过来的。
* contains(Object element):判断List集合中是否包含指定元素。该方法是从Collection集合继承过来的。
3. 查询指定元素索引
* indexOf(Object o):从前往后查找List集合元素,返回第一次出现指定元素的索引,如果此列表不包含该元素,则返回-1。
* lastIndexOf(Object o):从后往前查找List集合元素,返回第一次出现指定元素的索引,如果此列表不包含该元素,则返回-1。
4. 其他
* iterator():返回迭代器(Iterator)对象,迭代器对象用于遍历集合。该方法是从Collection集合继承过来的。
* size():返回List集合中的元素数,返回值是int类型。该方法是从Collection集合继承过来的。
* subList(int fromIndex, int toIndex):返回List集合中指定的 fromIndex(包括 )和 toIndex(不包括)之间的元素集合,返回值为List集合。
**提示** 在Java中任何集合中存放的都是对象,即引用数据类型,基本数据类型不能放到集合中。将整数1放到集合中,这是因为这个过程中发生了自动装箱,整数1被封装成Integer对象1,然后再放入到集合中。
### 20.3.2 遍历集合
集合最常用的操作之一是遍历,遍历就是将集合中的每一个元素取出来,进行操作或计算。List集合遍历有三种方法:
1. 使用for循环遍历:List集合可以使用for循环进行遍历,for循环中有循环变量,通过循环变量可以访问List集合中的元素。
2. 使用for-each循环遍历:for-each循环是针对遍历各种类型集合而推出的,笔者推荐使用这种遍历方法。
3. 使用迭代器遍历:Java提供了多种迭代器,List集合可以使用Iterator和ListIterator迭代器。
**示例代码如下:**
```
~~~
//HelloWorld.java文件
package com.a51work6;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class HelloWorld {
public static void main(String[] args) {
List list = new ArrayList();
String b = "B";
// 向集合中添加元素
list.add("A");
list.add(b);
list.add("C");
list.add(b);
list.add("D");
list.add("E");
// 1.使用for循环遍历
System.out.println("--1.使用for循环遍历--");
for (int i = 0; i < list.size(); i++) {
System.out.printf("读取集合元素(%d): %s \n", i, list.get(i)); ①
}
// 2.使用for-each循环遍历
System.out.println("--2.使用for-each循环遍历--");
for (Object item : list) { ②
String s = (String) item; ③
System.out.println("读取集合元素: " + s);
}
// 3.使用迭代器遍历
System.out.println("--3.使用迭代器遍历--");
Iterator it = list.iterator(); ④
while (it.hasNext()) { ⑤
Object item = it.next(); ⑥
String s = (String) item; ⑦
System.out.println("读取集合元素: " + s);
}
}
}
~~~
```
代码中第一行和第三行从集合中取出的元素都是Object类型
## 20.3 Set集合
Set集合是由一串无序的,不能重复的相同类型元素构成的集合。图20-3是一个班级的Set集合。这个Set集合中有一些学生,这些学生是无序的。
![](https://box.kancloud.cn/120d8842bf316c889775c09ac440cd3f_476x755.png)
Set接口直接实现类主要是HashSet,HashSet是基于散列表数据结构的实现。
### 20.3.1 常用方法
Set接口也继承自Collection接口,Set接口中大部分都是继承自Collection接口,这些方法如下。
1. 操作元素
* add(Object element):在Set集合的尾部添加指定的元素。该方法是从Collection集合继承过来的。
* remove(Object element):如果Set集合中存在指定元素,则从Set集合中移除该元素。该方法是从Collection集合继承过来的。
* clear():从Set集合中移除所有元素。该方法是从Collection集合继承过来的。
2. 判断元素
* isEmpty():判断Set集合中是否有元素,没有返回true,有返回false。该方法是从Collection集合继承过来的。
* contains(Object element):判断Set集合中是否包含指定元素,包含返回true,不包含返回false。该方法是从Collection集合继承过来的。
3. 其他
* iterator():返回迭代器(Iterator)对象,迭代器对象用于遍历集合。该方法是从Collection集合继承过来的。
* size():返回Set集合中的元素数,返回值是int类型。该方法是从Collection集合继承过来的。
### 20.3.2 遍历集合
Set集合中的元素由于没有序号,所以不能使用for循环进行遍历,但可以使用for-each循环和迭代器进行遍历。事实上这两种遍历方法也是继承自Collection集合,也就是说所有的Collection集合类型都有这两种遍历方式。
## 20.4 Map集合
Map(映射)允许按照某个键来访问元素。Map集合是由两个集合构成的,一个是键(key)集合,一个是值(value)集合。键集合是Set类型。值集合是Collection类型,可以有重复的元素。Map集合中的键和值是成对出现的。
图20-4所示是Map类型的“国家代号”集合。键是国家代号集合,不能重复。值是国家集合,可以重复
![](https://box.kancloud.cn/cfc5d2f917c3b5f79a98b9c6076c4bb8_865x560.png)
**图20-4 Map集合**
> **提示** Map集合更适合通过键快速访问值,就像查英文字典一样,键就是要查的英文单词,而值是英文单词的翻译和解释等。有一个英文单词会对应多个翻译和解释,这就是map键与值的关系。
Map接口直接实现类主要是HashMap,HashMap是基于散列表数据结构的实现。
### 20.4.1 常用方法
Map集合中包含两个集合(键和值),所以操作起来比较麻烦,Map接口提供很多方法用来管理和操作集合。主要的方法如下。
1. 操作元素
* get(Object key):返回指定键所对应的值;如果Map集合中不包含该键值对,则返回null。
* put(Object key, Object value):指定键值对添加到集合中。
* remove(Object key):移除键值对。
* clear():移除Map集合中所有键值对。
2. 判断元素
* isEmpty():判断Map集合中是否有键值对,没有返回true,有返回false。
* containsKey(Object key):判断键集合中是否包含指定元素,包含返回true,不包含返回false。
* containsValue(Object value):判断值集合中是否包含指定元素,包含返回true,不包含返回false。
3. 查看集合
* keySet():返回Map中的所有键集合,返回值是Set类型。
* values():返回Map中的所有值集合,返回值是Collection类型。
* size():返回Map集合中键值对数。
### 20.4.2 遍历集合
Map集合遍历与List和Set集合不同,Map有两个集合,因此遍历时可以只遍历值的集合,也可以只遍历键的集合,也可以同时遍历。这些遍历过程都可以使用for-each循环和迭代器进行遍历。
**示例代码如下:**
```
~~~
//HelloWorld.java文件
package com.a51work6;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HelloWorld {
public static void main(String[] args) {
Map map = new HashMap();
map.put(102, "张三");
map.put(105, "李四");
map.put(109, "王五");
map.put(110, "董六");
map.put(111, "李四");
// 1.使用for-each循环遍历
System.out.println("--1.使用for-each循环遍历--");
// 获得键集合
Set keys = map.keySet(); ①
for (Object key : keys) {
int ikey = (Integer) key; // 自动拆箱 ②
String value = (String) map.get(key); // 自动装箱 ③
System.out.printf("key=%d - value=%s \n", ikey, value);
}
// 2.使用迭代器遍历
System.out.println("--2.使用迭代器遍历--");
// 获得值集合
Collection values = map.values(); ④
// 遍历值集合
Iterator it = values.iterator();
while (it.hasNext()) {
Object item = it.next();
String s = (String) item;
System.out.println("值集合元素: " + s);
}
}
}
~~~
```