文章目录
- 集合
- 集合概述
- 集合体系核心框架图
- 分类
- 单列集合
- 双列集合
- 集合和数组的区别
- Collection
- 主要方法
- List
- ArrayList
- Vector
- Stack
- LinkedList
- Collection常用遍历方法
- Iterator遍历集合
- foreach遍历集合
- forEach遍历
- Set
- HashSet
- TreeSet
- Map
- HashMap
- TreeMap
- Map常用遍历方法
- Iterator遍历集合
- foreach遍历集合
- forEach遍历集合
- 集合特征图
- 小结
集合
集合概述
1、Java集合就是一个容器,用来存储Java对象的引用(通常称为对象)
2、这些集合位于java.util
包中
集合体系核心框架图
分类
单列集合
Collection:单列集合的根接口,用来存储一系列符合某种规则的元素,Collection有两个重要的接口,分别是List和Set
双列集合
Map:双列集合的根接口,用来存储具有键(Key)、值(Value)映射关系的元素,Map有两个重要的接口,分别是HashMap和TreeMap
集合和数组的区别
数组 | 集合 | |
长度区别 | 长度固定,不能增大或减小 | 长度可变,可以根据元素个数增大 |
数据类型 | 基本类型、引用类型 | 引用类型 |
内容区别 | 只能存储同一种数据类型 | 可以存储多种类型(一般为同一种) |
Collection
Collection接口是一个顶层接口,主要定义集合的约定
主要方法
方法 | 功能 |
boolean add(Object obj) | 向集合中添加一个元素obj |
boolean addAll(Collection c) | 将指定集合c中的所有元素添加到该集合中 |
boolean remove(Object obj) | 删除该集合中指定的元素 |
boolean removeAll(Collection c) | 删除集合中包含指定集合c中的所有元素 |
boolean isEmpty() | 判断集合是否为空 |
boolean contains(Object obj) | 判断集合中是否包含某个元素 |
boolean containsAll(Collection c) | 判断集合中是否包含指定的集合c中所有元素 |
void clear() | 清空集合 |
int size() | 返回集合中元素个数 |
List
1、List接口也算是一个顶层接口,继承了Collection接口,同时也是ArrayList,LinkedList等集合的父类
2、集合中元素有序,可以出现重复元素,可以通过索引访问元素
常用方法:
方法 | 功能 |
void add(int index,Object obj) | 将元素obj插入到List指定索引位置 |
boolean addAll(int index,Collection c) | 将集合c中所有元素插入到List指定的索引位置 |
Object get(int index) | 返回集合索引位置index的值 |
Object remove(int index) | 删除索引index的元素 |
Object set(int index,Object obj) | 将索引index位置的值替换为obj,返回替换前的值 |
int indexOf(Object obj) | 返回obj在集合中首次出现的位置 |
int lastIndexOf(Object obj) | 返回obj在集合中最后一次出现的位置 |
Object[] toArray() | 将集合元素转化为数组 |
void sort() | 将集合按指定比较规则排序 |
ArrayList
ArrayList是实现了List接口的可扩容数组(动态数组),它的内部封装了一个长度可变的数组对象
由于它的内部是数组,所以进行增删操作效率很低,但是数组结构允许通过索引来访问元素,所以ArrayList集合在遍历和查找时十分高效
但是有一点,ArrayList不是线程安全的容器,如果多个线程中至少两个线程修改了ArrayList的结构的话,就会导致线程安全问题
Vector
Vector和ArrayList一样,都是基于数组实现,只不过Vector是一个线程安全的容器,它的内部每个方法都上了锁,避免多线程引起的安全性问题,但是这种同步方式需要的开销比较大,所以访问元素的效率远远低于ArrayList
扩容上,Vector扩容后数组长度为原来的两倍,而ArrayList扩容每次增加50%,也就是原来的1.5倍
Stack
Stack继承了Vector类,提供了栈的常用方法:
方法 | 功能 |
Object push(Object obj) | 将元素推到栈顶 |
Object pop() | 移出并返回栈顶元素 |
Object peek() | 返回栈顶元素但不删除 |
boolean empty() | 判断栈是否为空 |
int search(Object obj) | 返回元素在栈中的位置,栈顶为1,不存在返回-1 |
LinkedList
LinkedList内部封装了一个双向链表,使用两个Node类型的first和last维护双向链表
所有元素通过链表联系起来,因此在做增删操作时,会有很高的效率
LinkedList除了继承Collection和List接口并实现集合的方法外,还提供了很多特殊的方法:
如下:
方法 | 功能 |
void add(int index,E element) | 在集合中指定位置添加元素obj |
void addFirst(Object obj) | 在集合开头插入obj |
void addLast(Object obj) | 在集合结尾插入obj |
Object getFirst() | 返回第一个元素 |
Object getLast() | 返回最后一个元素 |
Object removeFirst() | 移出并返回第一个元素 |
Object removeLast() | 移出并返回最后一个元素 |
boolean offer(Object obj) | 将指定元素添加到集合的结尾 |
boolean offerFirst(Object obj) | 将指定元素添加到集合的开头 |
boolean offerLast(Object obj) | 将指定元素添加到集合的结尾 |
Object peek() | 返回集合第一个元素 |
Object peekFirst() | 返回集合第一个元素 |
Object peekLast() | 返回集合最后一个元素 |
Object poll() | 移出并返回集合的第一个元素 |
Object pollFirst() | 移出并返回集合的第一个元素 |
Object pollLast() | 移出并返回集合的最后一个元素 |
void push(Object obj) | 将指定元素添加到集合开头 |
Object pop() | 移出并返回第一个元素 |
Collection常用遍历方法
Iterator遍历集合
Iterator主要用于迭代访问(遍历),所以Iterator对象又称为迭代器
举例如下:
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
Iterator iterator = list.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
}
或者简单些:
for(Iterator iterator = list.iterator();iterator.hasNext();){
System.out.println(iterator.next());
}
说明:
1、遍历元素时,首先通过调用ArrayList集合的iterator()方法获得迭代器对象,然后使用hasNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出
2、Iterator迭代器内部采用了指针的方式跟踪集合中的元素,在调用next()方法前,迭代器位于第一个元素之前,不指向任何元素,当开始调用next()方法时,迭代器会指向第一个元素并返回,当再次调用时,会指向第二个元素并返回…直到hasNext()返回false停止
foreach遍历集合
foreach循环是for循环的增强版,可以用于数组和集合,不需要知道数组/容器的长度,也不需要索引就可以自动访问
举例如下:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
for (Object obj : list) {
System.out.println(obj);
}
}
}
注:foreach循环虽然写起来很简单,但是也有局限性。使用foreach循环遍历集合或者数组时,只能访问,不能修改元素
forEach遍历
forEach遍历使用Lambda表达式
举例如下:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.forEach(obj-> System.out.println(obj));
}
}
Set
1、Set接口和List接口一样继承自Collection
2、集合中元素无序,并且不会重复出现
HashSet
HashSet是Set接口的一个实现类,存储的元素不可以重复,并且元素都是无序的,允许存在null
当向HashSet集合中添加一个元素时,首先会调用该元素的hashCode()方法来获取hash值和确定元素的存储位置,如果该位置没有元素则直接添加,若有元素,则调用equals()方法让添加的元素与该位置上的元素一一比较,如果返回false,则可以添加,如果返回true,则说明有重复元素,则直接把要添加的元素丢掉
当向集合中添加元素时,通常需要重写hashCode()和equals()方法,否则可能当添加相同的对象时因为地址不同而都添加成功
TreeSet
TreeSet是Set接口的另一个实现类,内部采用的是平衡二叉树存储元素,所以TreeSet集合中没有重复的元素,并且可以对元素进行排序
TreeSet在继承Set接口的基础上新增了一些方法:
如下:
方法 | 功能 |
Object first() | 返回TreeSet集合的第一个元素 |
Object last() | 返回TreeSet集合的最后一个元素 |
Object lower(Object obj) | 返回TreeSet集合中小于obj的最大元素,没有则返回null |
Object floor(Object obj) | 返回TreeSet集合中小于等于obj的最大元素,没有则返回null |
Object higher(Object obj) | 返回TreeSet集合中大于obj的最小元素,没有则返回null |
Object ceiling(Object obj) | 返回TreeSet集合中大于等于obj的最小元素,没有则返回null |
Object pollFirst() | 移出并返回集合的第一个元素 |
Object pollLast() | 移出并返回集合最后一个元素 |
元素在添加时,会进行比较,此时自动调用compareTo()方法
TreeSet有两种排序规则:自然排序和定制排序
1、自然排序:默认情况下都是使用自然排序
2、定制排序:创建时使用Comparator进行排序
Map
Map接口是一种双列集合,使用Key-Value键值对,键值之间存在一种一对一的映射关系,一个Key只能对应一个Value,并且Key不能重复,在访问集合中的元素的时候,指定了Key,就能找到对应的Value
Map接口定义了很多方法
如下:
方法 | 功能 |
voif put(Object key,Object value) | 向Map集合中添加元素 |
void clear() | 清空整个集合 |
int size() | 返回Map键值对个数 |
boolean containsKey(Object key) | 返回集合中是否存在指定的key |
boolean containsValue(Object value) | 返回集合中是否存在指定的value |
Object get(Object key) | 返回指定键对应的值,如果不存在此key,返回null |
Object remove(Object key) | 移出并返回指定的key对应的值value |
Set keySet() | 以Set集合的形式返回Map集合中所有的值对象value |
boolean remove(Object key,Object value) | 删除Map集合中指定的键值同时匹配的元素 |
boolean replace(Object key,Object value) | 将Map集合中指定的键key的值修改为value |
Object getOrDefault(Object key,Object defaultValue) | 返回Map集合中指定键对应的值,不存在则返回defaultValue |
HashMap
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap 是无序的,即不会记录插入的顺序。
HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
TreeMap
Map接口另一个常用类TreeMap,也是存储键值映射关系的元素,并且不能出现重复的key
TreeMap和TreeSet一样,会对存入的元素进行大小排序,也是有自然排序和定制排序两种
不同于HashMap的是,TreeMap内部是红黑树
Map常用遍历方法
Iterator遍历集合
1、第一种方式:
将所有的键key转化为Set集合,接着将Set集合转换为Iterator接口对象,然后遍历Map集合中所有的键,根据键获取对应的值
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap();
map.put("1", 101);
map.put("2", 102);
map.put("3", 103);
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
System.out.println(key + " : " + value);
}
}
}
2、第二种方式:
首先调用Map对象的entrySet()方法获得存储键值的Set集合,这个集合存放的是Map.Entry类型的元素,每个Map.Entry对象代表一个键值对,然后迭代Set集合,根据键获取对应的值
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap();
map.put("1", 101);
map.put("2", 102);
map.put("3", 103);
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println(key + " : " + value);
}
}
}
foreach遍历集合
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap();
map.put("1", 101);
map.put("2", 102);
map.put("3", 103);
for (Object key : map.keySet()) {
System.out.println(key + " : " + map.get(key));
}
}
}
forEach遍历集合
和Collection遍历集合的forEach方法一样,也是使用Lambda表达式
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap();
map.put("1", 101);
map.put("2", 102);
map.put("3", 103);
map.forEach((key, value) -> System.out.println(key + " : " + value));
}
}
集合特征图
集合 | 有序无序 | 是否随机访问 | 重复元素 | 空元素 | 线程安全 |
ArrayList | |||||
Vector | |||||
Stack | |||||
LinkedList | |||||
HashSet | |||||
TreeSet | |||||
HashMap | |||||
TreeMap |
小结
本篇文章只写了集合的基础部分总结,更深的内容没有提到,若有错误请指正