Java集合框架
Java集合框架
集合有时又称容方法,简单地说就是个对象,能将具有相同性质的多个元素汇聚成一个整体。
集合框架(Collections Framework)是用来表现和操纵集合的一个统一的体系结构。
Collection接口
Collection接口时Java集合框架的最顶层接口,它位于java.util
包中,是Set接口和List接口(后面会讲)的父接口。
转换构造法
Collection接口实现都有一个带有集合参数的构造方法。也就是说,在这里可以通过”转换”集合的类型来实现存储。
1 |
|
a可以是一个List、Set或另外一中Collection。通常,习惯地创建一个新的ArrayList,初始化为包含a中的所有元素。
1 |
|
通过“转换构造法”,list或set对象就包含了集合a中的所有元素。
Collection接口的定义
基本操作:
boolean add(E e)
: 将指定的元素添加到集合中(如果集合允许添加)。boolean remove(Object o)
: 从集合中移除指定的元素。boolean contains(Object o)
: 检查集合是否包含指定的元素。int size()
: 返回集合中的元素数量。boolean isEmpty()
: 检查集合是否为空。Iterator<E> iterator()
: 返回一个迭代器,用于遍历集合中的元素。
以及批量操作:
boolean addAll(Collection<? extends E> c)
: 批量添加boolean removeAll(Collection<?> c)
: 从集合中批量移除元素。boolean containsAll(Collection<?> c)
: 检查当前集合是否包含所有传入集合的元素bollean retainAll(Collection<?> c)
: 删除当前集合中所有不在指定集合c
中的元素void clear()
: 移除集合中的所有元素。
数组操作:
Object[] toArray()
: 将集合转换为数组,数组类型为object<T> T[] toArry(T[] a)
: 将集合中的元素转换为指定类型的数组,并将其存储在提供的数组中。如果提供的数组足够大,则元素将被存储在这个数组中;否则,将创建一个新的数组。
Collection接口的基本操作
1 |
|
这里我创建了一个dog对象,并给它name和age。
要注意的是,iterator迭代方法同样有遍历的功能,但是Iterator.remove是修改集合唯一安全的方法。如果要移除当前元素。for-each结构隐藏迭代方法,因此不能调用remove方法。同样在多重集合上进行并行迭代也要用迭代器迭代。
下面演示如何过滤Collection集合:
1 |
|
Collection接口的批量操作
下面展示表现批量操作强大功能的一个示例,从一个名为c的Collection中移除一个指定元素e的所有实例:
1 |
|
或者也可以移除所有null元素:
1 |
|
Collections.singleton是一个静态工厂方法,返回一个只包含指定元素的不可变Set集合(没有重复元素)。
在例子中Collections.singleton(e)方法只包含元素e的Set集合,然后就可以用removeAll删除。
Collection数组操作
toArray()方法主要作为集合和老的期望输入数组的API之间的桥梁。
1 |
|
Set接口
Set是一个不能包含重复元素的接口,是Collection接口的子接口,并且只包含从Collection继承过来的方法,并增加了对add()方法的使用限制,不允许有重复的元素。Set()还修改了equals()和hashCode()方法的实现,允许对Set实例进行内容上的比较,即使它们实现类型不同。如果两个Set实例包含相同的元素,那么它们就是相等的。
Set定义
主要方法:
- 继承了
Collection
接口的所有方法。 - 没有专门定义新的方法,但子接口和实现类提供了对集合不重复性要求的具体实现。
主要实现类:
HashSet
: 基于哈希表的实现,不保证元素的顺序,通常提供快速的插入、删除和查找操作。TreeSet
: 基于红黑树的实现,按自然顺序或构造时提供的比较器进行排序。LinkedHashSet
: 结合了哈希表和链表的特点,保持插入顺序的同时提供较快的操作速度。
Java平台包含3个通用目的的Set实现就是HashSet、TreeSet、LinkedHashSet这三个。
Set接口的基本操作
那么Set和Collection有什么区别呢?下面看这个实例。
1 |
|
我们可以看到,这其中最大的区别就是Set不能重复添加元素。
Set接口的批量操作
批量操作特别适合于Set接口:
- s1.containsAll(s2):如果s2是s1的一个子集合,返回true
- s1.addAll(s2):将s1变换为s1和s2的并集
- s1.retain(s2):将s1变换为s1和s2的交集
- s1.removeAll(s2):将s1不对称地变换为s1和s2的差集
addAll示例:
1 |
|
removeAll示例:
1 |
|
List接口
List是一个有序的集合(又是被称为序列)。List可以包含重复的元素。除了从Collection继承过来的操作之外,List接口还包括以下操作:
- 按位置访问:根据元素在序列中的位置索引访问元素
- 查找:在序列中查找指定对象,并返回其位置索引
- 迭代:扩展了Iteractor接口,以利用序列的顺序特性
- List子集合:在序列上执行任意范围的操作
List接口的定义
如下:
1 |
|
Java平台常见的List实现包括: ArrayList
(基于动态数组)、LinkedList
(基于双向链表)和 Vector
(线程安全的动态数组)。
List接口的操作
1. 添加元素
void add(int index, E element)
- 在指定位置插入元素。
示例:
1
2
3
4List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add(1, "Orange"); // 在位置 1 插入 "Orange"boolean addAll(int index, Collection<? extends E> c)
- 从指定位置开始,将指定集合中的所有元素添加到当前列表中。
示例:
1
2
3
4
5
6List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
List<String> newItems = Arrays.asList("Orange", "Grapes");
list.addAll(1, newItems); // 从位置 1 开始添加 newItems 中的元素
2. 访问元素
E get(int index)
- 获取指定位置的元素。
示例:
1
2
3
4
5List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
String item = list.get(0); // 获取位置 0 的元素E set(int index, E element)
- 替换指定位置的元素。
示例:
1
2
3
4
5List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.set(1, "Orange"); // 将位置 1 的元素替换为 "Orange"
3. 删除元素
E remove(int index)
- 移除指定位置的元素。
1
2
3
4
5List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.remove(1); // 移除位置 1 的元素
4. 查找元素
int indexOf(Object o)
- 返回指定元素第一次出现的索引,如果不在列表中,则返回 -1。
示例:
1
2
3
4
5List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
int index = list.indexOf("Banana"); // 获取 "Banana" 的位置int lastIndexOf(Object o)
- 返回指定元素最后一次出现的索引,如果不在列表中,则返回 -1。
示例:
1
2
3
4
5
6List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Banana");
int index = list.lastIndexOf("Banana"); // 获取 "Banana" 最后出现的位置
5. 子列表
List<E> subList(int fromIndex, int toIndex)
- 返回当前列表中从
fromIndex
(包含)到toIndex
(不包含)的部分列表。
1
2
3
4
5
6
7List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
list.add("Date");
List<String> subList = list.subList(1, 3); // 获取子列表 [Banana, Cherry]- 返回当前列表中从
6. 迭代器
ListIterator<E> listIterator()
- 返回一个
ListIterator
,从列表的开始处迭代。
- 返回一个
ListIterator<E> listIterator(int index)
- 返回一个
ListIterator
,从指定的位置开始迭代。
1
2
3
4
5
6
7
8
9
10
11
12
13
14List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
ListIterator<String> iteratorFromIndex = list.listIterator(1);
while (iteratorFromIndex.hasNext()) {
System.out.println(iteratorFromIndex.next());
}- 返回一个
Map接口
Map接口的定义
1 |
|
Java平台包括3中通用的Map实现:HashMap、TreeMap和LinkedHashMap。
Map接口的基本操作
1. 基本操作
int size()
- 返回
Map
中键值对的数量。
示例:
1
2
3
4
5Map<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
int size = map.size(); // 返回 2- 返回
boolean isEmpty()
- 检查
Map
是否为空(即是否没有键值对)。
示例:
1
boolean isEmpty = map.isEmpty(); // 返回 false
- 检查
2. 键和值的存在性检查
boolean containsKey(Object key)
- 检查
Map
是否包含指定的键。
示例:
1
boolean hasKey = map.containsKey("One"); // 返回 true
- 检查
boolean containsValue(Object value)
- 检查
Map
是否包含指定的值。
示例:
1
boolean hasValue = map.containsValue(2); // 返回 true
- 检查
3. 获取和设置键值对
V get(Object key)
- 根据键获取对应的值。如果键不存在,则返回
null
。
示例:
1
Integer value = map.get("One"); // 返回 1
- 根据键获取对应的值。如果键不存在,则返回
V put(K key, V value)
- 将指定的键值对添加到
Map
中。如果键已经存在,则更新对应的值,并返回之前的值。
示例:
1
map.put("Three", 3); // 将 "Three" 键与 3 值添加到 map 中
- 将指定的键值对添加到
V remove(Object key)
- 根据键移除对应的键值对,并返回被移除的值。
示例:
1
Integer removedValue = map.remove("Two"); // 移除 "Two" 键对应的值 2
4. 批量操作
void putAll(Map<? extends K, ? extends V> m)
- 将指定
Map
中的所有键值对添加到当前Map
中。
示例:
1
2
3
4
5Map<String, Integer> anotherMap = new HashMap<>();
anotherMap.put("Four", 4);
anotherMap.put("Five", 5);
map.putAll(anotherMap); // 将 anotherMap 的所有键值对添加到 map 中- 将指定
void clear()
- 移除
Map
中的所有键值对,使Map
变为空。
示例:
1
map.clear(); // 清空 map
- 移除
5. 视图操作
Set<K> keySet()
- 返回
Map
中所有键的集合。
示例:
1
Set<String> keys = map.keySet(); // 获取 map 的所有键
- 返回
Collection<V> values()
- 返回
Map
中所有值的集合。
示例:
1
Collection<Integer> values = map.values(); // 获取 map 的所有值
- 返回
Set<Map.Entry<K, V>> entrySet()
- 返回
Map
中所有键值对的集合,每个键值对作为Map.Entry
对象存在。
示例:
1
2
3
4Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}- 返回
6. 嵌套接口 Entry
K getKey()
- 返回
Map.Entry
对象中的键。
- 返回
V getValue()
- 返回
Map.Entry
对象中的值。
- 返回
V setValue(V value)
- 设置
Map.Entry
对象中的值,并返回之前的值。
- 设置
boolean equals(Object o)
- 判断两个
Map.Entry
对象是否相等。
- 判断两个
int hashCode()
- 返回
Map.Entry
对象的哈希码。
- 返回
示例
比如我们可以做一个数组中单词的显示次数小程序:
1 |
|
args:
1 |
|
output:
1 |
|