Collections(集合工具类)
可变参数
就是一种特殊形参,定义在方法、构造器的形参列表里,定义格式是:方法名(数据类型… 形参名称){ }
可变参数的特点和好处
**特点:**可以不传数据给它;可以传一个或者同时传多个数据给它;也可以传一个数组给它。
**好处:**常常用来灵活的接收数据。可变参数的注意事项
- 可变参数在方法内部就是一个数组
- 一个形参列表中可变参数只能有一个
- 可变参数必须放在形参列表的最后面
Collections
- java.utils.Collections:是集合工具类
- 作用: Collections并不属于集合,是用来操作集合的工具类。
Collections常用的API
方法名称 | 说明 |
---|---|
public static boolean addAll(Collection<? super T> c, T… elements) | 给集合对象批量添加元素 |
public static void shuffle(List<?> list) | 打乱List集合元素的顺序 |
Collections排序相关API
- 使用范围:只能对于List集合的排序。
排序方式1:
方法名称 | 说明 |
---|---|
public static void sort(List list) | 将集合中元素按照默认规则排序 |
注意:本方式不可以直接对自定义类型的List集合排序,除非自定义类型实现了比较规则Comparable接口。
排序方式2:
方法名称 | 说明 |
---|---|
public static void sort(List list,Comparator<? super T> c) | 将集合中元素按照指定规则排序 |
Map集合
概述
- Map集合称为双列集合,一次需要存一对数据做为一个元素, 格式:{key1=value1 , key2=value2 , key3=value3 , …}
- Map集合的每个元素分为两部分:key和value,key称为键,value称为值,整体叫键值对,因此Map也叫“键值对集合”
- Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值
Map集合是什么, 使用场景?
Map集合是键值对集合
Map集合非常适合做类购物车这样的业务场景。
特点
HashMap: 无序、不重复(用的最多)
LinkedHashMap :有序、不重复 无索引
TreeMap: 按照大小默认升序排序、不重复 无索引
常用方法
- 为什么使用Map集合
- Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。
- Map API如下:
方法名称 | 说明 |
---|---|
public V put(K key,V value) | 添加/修改元素 |
public int size() | 获取集合的大小 |
public void clear() | 清空集合 |
public boolean isEmpty() | 判断集合是否为空 |
public V get(Object key) | 根据键获取对应值 |
public V remove(Object key) | 根据键删除整个元素 |
public boolean containsKey(Object key) | 判断是否包含某个键 |
public boolean containsValue(Object value) | 判断是否包含某个值 |
public Set keySet() | 获取全部键的集合 |
public Collection values() | 获取Map集合的全部值 |
遍历方式(三种)
Map集合的遍历方式一
先获取Map集合全部的键,再通过遍历键来找值
方法名称 | 说明 |
---|---|
public Set keySet() | 获取所有键的集合 |
public V get(Object key) | 根据键获取其对应的值 |
Map集合的遍历方式二
把“键值对”看成一个整体进行遍历
Map提供的方法 | 说明 |
---|---|
Set<Map.Entry<K, V>> entrySet() | 获取所有“键值对”的集合 |
Map.Entry提供的方法 | 说明 |
---|---|
K getKey() | 获取键 |
V getValue() | 获取值 |
Map集合的遍历方式三
需要用到Map的如下方法
方法名称 | 说明 |
---|---|
default void forEach(BiConsumer<? super K, ? super V> action) | 结合lambda遍历Map集合 |
HashMap
Map集合体系
底层原理
HashMap跟HashSet的底层原理是一模一样的,都是基于哈希表实现的。
实际上:原来学的Set系列集合的底层就是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
public HashSet() { map = new HashMap<>(); }
哈希表
- JDK8之前,哈希表 = 数组+链表
- JDK8开始,哈希表 = 数组+链表+红黑树
- 哈希表是一种增删改查数据,性能都较好的数据结构。
HashMap底层是基于哈希表实现的
- HashMap集合是一种增删改查数据,性能都较好的集合
- 但是它是无序,不能重复,没有索引支持的(由键决定特点)
- HashMap的键依赖hashCode方法和equals方法保证键的唯一
- 如果键存储的是自定义类型的对象,可以通过重写hashCode和equals方法,这样可以保证多个对象内容一样时,HashMap集合就能认为是重复的。
总结
HashMap如何实现键的唯一性的?
- 依赖hashCode方法和equals方法保证键的唯一。
- 如果键要存储的是自定义对象,需要重写hashCode和equals方法。
HashMap的特点
- HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引
- 没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
- HashMap跟HashSet底层原理是一模一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已。
实际上:Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
LinkedHashMap
原理
底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)。
由键决定: 有序 不重复 无索引
TreeMap
TreeMap集合的特点是怎么样的?
- 根据键可排序、不重复、无索引
- 底层基于红黑树实现排序,增删改查性能较好
TreeMap集合自定义排序规则有几种方式
- 2种。
- 类实现Comparable接口,重写比较规则。
- 集合自定义Comparator比较器对象,重写比较规则。
集合嵌套
指的是集合中的元素又是一个集合
案例: Map集合案例-省和市
需求
要求在程序中记住如下省份和其对应的城市信息,记录成功后,要求可以查询出湖北省的城市信息。江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市分析
- 定义一个Map集合,键用表示省份名称,值表示城市名称,注意:城市会有多个。Map<String,List>
- 根据“湖北省”这个键获取对应的值展示即可。
public static void main(String[] args) { HashMap<Object, List<String>> map = new HashMap<>(); map.put("江苏省", Arrays.asList("南京市", "扬州市", "苏州市", "无锡市", "常州市")); map.put("湖北省", Arrays.asList("武汉市", "孝感市", "十堰市", "宜昌市", "鄂州市")); ArrayList<String> arrayList = new ArrayList<>(); Collections.addAll(arrayList, "石家庄市", "唐山市", "邢台市", "保定市", "张家口市"); map.put("河北省", arrayList); List<String> list = map.get("湖北省"); for (String s : list) { System.out.println(s); } }
Stream流
什么是Stream?
- 也叫Stream流,是Jdk8开始新增的一套API (java.util.stream.*),可以用于操作集合或者数组的数据。
- 优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好。
Stream流的作用是什么,结合了什么技术?
- 简化集合、数组操作的API。结合了Lambda表达式。
Stream流的思想和使用步骤
- 先得到集合或者数组的Stream流(就是一根传送带)。
- 然后调用Stream流的方法对数据进行处理(操作)
- 获取处理的结果(终结)
常用方法
集合获取Stream流的方式
可以使用Collection接口中的默认方法stream()生成流
名称 | 说明 |
---|---|
default Stream stream() | 获取当前集合对象的Stream流 |
数组获取Stream流的方式
名称 | 说明 |
---|---|
public static Stream stream(T[] array) | 获取当前数组的Stream流 |
public static Stream of(T… values) | 获取当前数组/可变数据的Stream流 |
Stream流的常用API(中间操作方法)
Stream提供的常用中间方法 | 说明 |
---|---|
Stream filter(Predicate<? super T> predicate) | 用于对流中的数据进行过滤。 |
Stream sorted() | 对元素进行升序排序 |
Stream sorted(Comparator<? super T> comparator) | 按照指定规则排序 |
Stream limit(long maxSize) | 获取前几个元素 |
Stream skip(long n) | 跳过前几个元素 |
Stream distinct() | 去除流中重复的元素。 |
Stream map(Function<? super T,? extends R> mapper) | 对元素进行加工,并返回对应的新流 |
static Stream concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
注意:
- 中间方法也称为非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程。
- 在Stream流中无法直接修改集合、数组中的数据。
Stream流的常见终结操作方法
Stream提供的常用终结方法 | 说明 |
---|---|
void forEach(Consumer action) | 对此流运算后的元素执行遍历 |
long count() | 统计此流运算后的元素个数 |
Optional max(Comparator<? super T> comparator) | 获取此流运算后的最大值元素 |
Optional min(Comparator<? super T> comparator) | 获取此流运算后的最小值元素 |
终结方法指的是调用完成后,不会返回新Stream了,没法继续使用流了。
它的作用是对流中的数据进行筛选(遍历、最大、最小、统计个数)
Stream流的收集方法
收集方法就是把Stream流操作后的结果转回到集合或者数组中去返回。
名称 | 说明 |
---|---|
R collect(Collector collector) | 开始收集Stream流,指定收集器 |
Collectors工具类提供了具体的收集方式
名称 | 说明 |
---|---|
public static Collector toList() | 把元素收集到List集合中 |
public static Collector toSet() | 把元素收集到Set集合中 |
public static Collector toMap(Function keyMapper , Function valueMapper) | 把元素收集到Map集合中 |
- 收集Stream流的作用 ?
- Stream流是操作集合/数组的手段
- 操作的结果数据最终要恢复到集合或者数组中去。
递归
认识递归
什么是递归?
- 递归是一种算法,在程序设计语言中广泛应用。
- 从形式上说:方法调用自身的形式称为方法递归( recursion)。
递归的形式
- 直接递归:方法自己调用自己。
- 间接递归:方法调用其他方法,其他方法又回调方法自己。
使用方法递归时需要注意的问题:
- 递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误。