Stream流
一、Stream流
1.1 不可变集合
不可变集合是jdk9加入的新特性,不可变集合就是不可以修改、添加或删除的集合,只能查找。使用场景如:斗地主游戏的牌库、计算机硬件信息等。
方法名 | 说明 |
---|---|
List.of(E… elements) | 创建List的不可变集合,可以同时加入多个元素。 |
Set.of(E… elements) | 创建Set的不可变集合,可以同时加入多个元素但不能有重复元素 |
Map.of(K k1,V v1…K10 k,V10 v) | 创建Map的不可变集合,不能有重复键且最多只能同时添加10个键值对 |
Map.ofEntries(Map.Entry<? extends K,? extends V>… entries) | 创建Map的不可变集合,元素可以超过10个 |
Map.copyof(Map<K,V> map) | 根据已有Map集合创建不可变的Map集合,(JDK10开始支持)如果已有集合是不可变集合就返回该集合本身,如果不是则在方法内部使用上面Map.ofEntries()方法创建对应的不可变集合。 |
Map集合不可以使用可变参数创建不可变集合的原因:可变参数必须是在所有参数的最末尾,而Map集合需要K、V的键值对,使用可变参数需要给他们全部设为可变参数,但形参中可变参数只能有一个。
示例代码
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Work01 {
public static void main(String[] args) {
List<String> list = List.of("张三","李四","王五","赵六","陈七");
for (String s : list) {
System.out.println(s);
}
System.out.println("-------------------------------------------");
Set<String> set = Set.of("张三", "李四", "王五", "赵六", "陈七");
for (String s : set) {
System.out.println(s);
}
System.out.println("-------------------------------------------");
Map<String, String> map = Map.of("张三", "李四", "王五", "赵六", "陈七", "黄八");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey()+"---"+entry.getValue());
}
System.out.println("-------------------------------------------");
/*
//获取到所有的键值对对象(Entry对象)
Set<Map.Entry<String, String>> entries = hm.entrySet();
//把entries变成一个数组
Map.Entry[] arr1 = new Map.Entry[0];
//toArray方法在底层会比较集合的长度跟数组的长度两者的大小
//如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
//如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用
Map.Entry[] arr2 = entries.toArray(arr1);
//此处创建了一个不可变的map集合
Map map = Map.ofEntries(arr2);
*/
Map map1 = Map.ofEntries(entries.toArray(new Map.Entry[0]));
map1.forEach((k,v)-> System.out.println(k+"+++"+v));
System.out.println("-------------------------------------------");
Map<String, String> map2 = Map.copyOf(map);
map2.forEach((k,v)-> System.out.println(k+"——"+v));
}
}
1.2 Stream流
1.2.1 Stream流的概念及作用
Stream流操作是Java 8一个重要新特性,它允许开发人员以声明性方式处理集合,其核心类库主要改进了对集合类的 API和新增Stream操作。Stream类中每一个方法都对应集合上的一种操作。Stream流结合Lambda表达式,简化了集合、数组的操作。
Stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。在Stream中的操作每一次都会产生新的流,内部不会像普通集合操作一样立刻获取值,而是惰性取值 ,只有等到用户真正需要结果的时候才会执行。并且对于现在调用的方法,本身都是一种高层次构件,与线程模型无关。因此在并行使用中,开发者们无需再去操心线程和锁了。Stream内部都已经做好了 。
1.2.2 Stream流的使用步骤
创建->中间操作->终端操作
1.2.3 Stream流的创建
获取方式 | 方法名 | 说明 |
---|---|---|
单列集合 | default Stream stream() | Collection中的默认方法 |
双列集合 | 无 | 无法直接使用Stream流 |
数组 | public static Streamstream(T[] array) | Arrays工具类中的静态方法 |
一堆零散数据 | public staticStreamof(T… values) | Stream接口中的静态方法 |
更多方法请自行探索
示例代码
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo01 {
public static void main(String[] args) {
//单列集合创建Stream流
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三", "李四", "王五");
// Stream<String> stream1 = list.stream();
// stream1.forEach(s -> System.out.println(s));
//将上两步合成一步链式编程书写
list.stream().forEach(s -> System.out.println(s));
System.out.println("-----------------------------");
//双列集合创建Stream流
HashMap<Integer, String> hm = new HashMap<>();
hm.put(1, "张三");
hm.put(2, "李四");
hm.put(3, "王五");
// Set<Map.Entry<Integer, String>> entries = hm.entrySet();
// Stream<Map.Entry<Integer, String>> stream2 = entries.stream();
// stream2.forEach(entry -> System.out.println(entry));
//将上三步合成一步
hm.entrySet().stream().forEach(entry -> System.out.println(entry));
System.out.println("-----------------------------");
//keySet方法获取
hm.keySet().stream().forEach(key -> System.out.println(key+"--"+hm.get(key)));
System.out.println("-----------------------------");
//数组创建Stream流
String[] array = {
"张三", "李四", "王五"};
// Stream<String> stream3 = Arrays.stream(array);
// stream3.forEach(s -> System.out.println(s));
//同上
Arrays.stream(array).forEach(s -> System.out.println(s));
System.out.println("-----------------------------");
//零散数据创建Stream流
// Stream<String> stream4 = Stream.of("张三", "李四", "王五");
// stream4.forEach(s -> System.out.println(s));
//同上
Stream.of("张三", "李四", "王五").forEach(s -> System.out.println(s));
}
}
Stream接口中静态方法of的形参是一个可变参数,可以传递一堆零散数据也可以传递一个数组,但数组必须是引用类型的,如果传递基本数据类型,则会把整个数组当做对象放到Stream中。
1.2.4 Stream流中间方法***
方法名 | 说明 |
---|---|
Stream filter(Predicate<? super T> predicate) | 过滤 |
Stream limit(long maxSize) | 获取前几个元素 |
Stream skip(long n) | 跳过前几个元素 |
Stream distinct() | 元素去重,依赖hashCode()和equals() |
static Stream concat(Stream a,Stream b) | 合并a和b两个流为一个流 |
Stream map(Function<T,R> mapper) | 转换流中的数据类型 |
中间方法会返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
链式编程可读性较差,可以将其折行以提高可读性
修改Stream流中的数据,不会影响原来集合或者数组中的数据
示例代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.stream.Stream;
public class StreamDemo02 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张3", "李4", "王5","赵6","韩7","张3","张3","张0");
ArrayList<String> list1 = new ArrayList<>();
Collections.addAll(list1, "张三", "李四", "王五","赵六","韩七","张三","张三","张十");
//过滤操作 Stream<T>filter(Predicate<? super T> pre