前言
本篇博客主要讲述了Java集合框架的基础知识,及部分集合的内部方法是如何实现的,学习集合框架的意义。
学习目标
- 学会熟练使用集合框架,以助我们能够更加便捷、快速的写出高效、稳定的代码。
- 学习背后的数据结构知识,理解各个集合的优缺点及使用场景。
一、Java集合框架是什么?
Java 集合框架 (Java Collection Framework) ,又被称为容器 (container) ,是定义在
java.util 包下的一组接口 (interfaces) 和其实现类 (classes) 。其主要表现为将多个元素 (element)
置于一个单元中,用于对这些元素进行快速 、便捷的存储 、检索 、管理 ,即平时我们俗称的增删查改 CRUD 。
简而言之 ,集合框架就是用来装数据的 “口袋” 。 我们日常生活中会因为装的东西不同而选择不同类型的袋子,如买菜的时候会用菜篮子,上课的时候会背包,游玩的时候会带钱包。同样的,根据对数据的使用情况不同,我们也会采取不同类型的集合来存储数据。
下面这张图中棕色并有汉字描述的框框就是后续要讲解的集合类,接口主要讲解Collection和Map,其他不会具体讲解,但是至少要能够记住整幅图的继承实现关系。
下面这幅图介绍了常用的几个辅助接口和类,如用来迭代遍历的迭代器、进行两个对象比较的比较器、对数组和集合进行操作的工具类,这些都会在后续文章中进行讲解。
二、学习接口
1. 基本关系简介
- Collection :用来存储管理一组对象 objects ,这些对象一般被成为元素 elements
- Set : 内部元素不能重复,背后隐含着查找/搜索的语义
- SortedSet : 一组有序的不能重复的元素
- List : 线性结构,如之前讲解过的顺序表与链表
- Queue : 队列
- Deque : 双端队列
- Set : 内部元素不能重复,背后隐含着查找/搜索的语义
- Map : 键值对 Key-Value-Pair ,背后隐含着查找/搜索的语义
- SortedMap : 一组有序的键值对
1. Collection
常用方法
方法签名 | 说明 |
---|---|
boolean add(E e) | 将元素 e 放入集合中 |
void clear() | 删除集合中的所有元素 |
boolean isEmpty() | 判断集合是否没有任何元素,俗称空集合 |
boolean remove(Object e) | 如果元素 e 出现在集合中,删除其中一个 |
int size() | 返回集合中的元素个数 |
Object[] toArray() | 返回一个装有所有集合中元素的数组 |
代码示范
import java.util.*;
public class 初识集合 {
public static void main(String[] args) {
/**
* Collection是接口, 所以不可以直接创建实例
* 在这里借用一下ArrayList来进行向上转型(ArrayList是Collection的子类, 忘记的可以去看看前面的那张图)
* 注意这里Collection collection = new ArrayList();
* 我们平常都是采用上面的方式来进行new对象的
* 但是这里使用了<Integer>来进行泛型约束, 这个知识点后续也会写成博客
* 这里只需要明白这是用来固定集合内元素类型的, 之后只能往里装int类型数据(Integer是int的包装类)
* 反之, 如果不进行约束就会导致可以往里面添加各种种类的元素
*/
Collection<Integer> collection = new ArrayList<>();
// 添加元素
collection.add(1);
collection.add(2);
collection.add(3);
// 判断集合是否为空
System.out.println(collection.isEmpty());
// 打印一下内部元素, 由于重写了toString()方法, 故打印出来的并不是哈希值, 而是集合内容
System.out.println(collection);
// 如果出现当前元素, 就删除此元素
collection.remove(1);
// 打印集合长度
System.out.println(collection.size());
// 集合转为数组
Integer[] arr1 = collection.toArray(new Integer[collection.size()]);
System.out.println("arr1: " + Arrays.toString(arr1));
Object[] arr2 = collection.toArray();
System.out.println("arr2: " + Arrays.toString(arr2));
// 清空集合
collection.clear();
// 判断集合是否为空
System.out.println(collection.isEmpty());
/**
* 注意不可采用下面这种方式进行数组类型转化
* 数组不能整体转换类型, 转换类型只适用于单个元素
* 如 int tmp = (int) 9.34
* 如果一定要转换数组的每个元素类型,可以通过遍历的方式进行依次转化
*/
Integer[] arr3 = (Integer[]) collection.toArray();
System.out.println("arr3: " + Arrays.toString(arr3));
}
}
执行结果如下:
2. Map
常用方法
方法签名 | 说明 |
---|---|
V get(Object k) | 根据指定的 k 查找对应的 v |
V getOrDefault(Object k, V defaultValue) | 根据指定的 k 查找对应的 v,没有找到用默认值代替 |
V put(K key, V value) | 将指定的 k-v 放入 Map |
boolean containsKey(Object key) | 判断是否包含 key |
boolean containsValue(Object value) | 判断是否包含 value |
Set<Map.Entry<K, V>> entrySet() | 将所有键值对返回 |
boolean isEmpty() | 判断是否为空 |
int size() | 返回键值对的数量 |
代码示范
public class 初识集合 {
public static void main(String[] args) {
/**
* Map是接口, 所以不可以直接创建实例
* 在这里借用一下HashMap来进行向上转型(HashMap是Map的子类, 忘记的可以去看看前面的那张图)
* 键的类型是整型, 值的类型是字符串
*/
Map<Integer, String> map = new HashMap<>();
// 新增键值对, 注意Map是根据函数计算来进行存储的, 故存储顺序并不等于插入顺序
map.put(1, "张三");
map.put(3, "王五");
map.put(2, "李四");
map.put(4, "赵六");
// // 打印一下内部键值对, 由于重写了toString()方法, 故打印出来的并不是哈希值, 而是集合内容
System.out.println(map);
// 根据键获取对应的值, 如果没有当前键, 就返回null
String str1 = map.get(1);
System.out.println("str1: " + str1);
// 根据键获取对应的值, 如果没有当前键, 就采用默认值
String str2 = map.getOrDefault(1, "查无此人");
System.out.println("str2: " + str2);
// 检查是否存在当前键
System.out.println(map.containsKey(1));
System.out.println(map.containsKey(6));
// 检查是否存在当前值
System.out.println(map.containsValue("张三"));
System.out.println(map.containsValue("zhangsan"));
// 获取到每一个键值对
// map.entrySet()获取到的是一个Set, 里面每一个元素就是一个键值对
// 这个键值对的类型被称为Entry, 是Map的一个内部类
for (Map.Entry<Integer, String> tmp:map.entrySet()) {
// 获取当前键值对的值
System.out.println(tmp.getValue());
// 获取当前键值对的键
System.out.println(tmp.getKey());
}
// 检查当前是否含有键值对
System.out.println(map.isEmpty());
// 输出键值对个数
System.out.println(map.size());
}
}
执行结果如下: