1 什么是 Stream,有什么作用?
原来你是这样的 Stream —— 浅析 Java Stream 实现原理
在之前所学的相关知识中,集合类是我们常用的存储一组数据的结构,但是如果需要对其中的数据进行处理,就会发现有些棘手,Java 提供流这种概念,抽象的可以理解是现实生活中的流水线技术,将所有数据放在流水线上,操作十分方便,利于我们处理这些数据。
2 代码实践整理
2.1 获取流的方式
package cn.edu.njust.streamdemo;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
* 获取 stream 流的几种方式
*/
public class StreamDemo01 {
public static void main(String[] args) {
// getStreamByList();
getStreamByDoubleList();
// getStreamByArrays();
// getStreamByStatic();
}
/**
* 单列集合获取流
*/
public static void getStreamByList() {
List<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3");
Stream<String> stringStream = list.stream();
// 使用forEach遍历,需要使用到匿名内部类
stringStream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
// 将匿名内部类简化为Lambda表达式
stringStream.forEach(s -> {
System.out.println(s);
});
}
/**
* 双列集合Map转化为流
*/
public static void getStreamByDoubleList() {
Map<String, Integer> hm = new HashMap<>();
hm.put("c", 0);
hm.put("c++", 1);
hm.put("Java", 2);
hm.put("python", 3);
// keySet() 将键转化为一个 Set 集合,只保留键
Set<String> keySet = hm.keySet();
Stream<String> keyStream = keySet.stream();
System.out.print("将键转化为流:");
keyStream.forEach(s -> {
System.out.print(s + ' ');
});
System.out.println();
// 将值转化为流
Stream<Integer> valueStream = hm.values().stream();
System.out.print("将值转化为流:");
valueStream.forEach(integer -> {
System.out.print(integer + " ");
});
System.out.println();
// 直接将整个键值对转化为单列集合,保留键和值
System.out.print("将Map转化为键值对流:");
hm.entrySet().stream().forEach(s -> {
System.out.print(s + " ");
});
}
/**
* Arrays 中的方法
*/
public static void getStreamByArrays() {
int[] arr = {1, 2, 3, 4};
IntStream intStream = Arrays.stream(arr);
intStream.forEach(e -> {
System.out.println(e);
});
}
/**
* 使用Stream中的of静态方法
*/
public static void getStreamByStatic() {
// of方法是个可变参数的方法
Stream.of(1, 2, 3, 4, 5).forEach(elem -> {
System.out.println(elem);
});
}
}
2.2 Stream 常用的中间方法
package cn.edu.njust.streamdemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
/**
* Stream 中常用的中间方法
*/
public class StreamDemo02 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(list, "c", "java", "c++", "java", "python");
// testFilter();
// testLimit(list);
// testSkip(list);
// testDistinct(list);
testConcat(list);
}
/**
* 过滤器筛选元素
*/
public static void testFilter() {
List<String> list = new ArrayList<>();
Collections.addAll(list, "c", "c++", "java", "python");
Stream<String> stream = list.stream();
// filter过滤器,根据某种条件筛选流中的元素
stream.filter(s -> s.startsWith("c")).forEach(s -> System.out.println(s));
/*
* 上述代码可以直接简写为如下
* 这样书写的原因是,流获取之后,只能进行一次处理,不能重复处理,所以没有必要使用一个变量保存
* 为了方便阅读,最好换行增加代码的可读性
* */
list.stream()
.filter(s -> s.startsWith("c"))
.forEach(s -> System.out.println(s));
}
/**
* 测试 limit 方法
*
* @param list [c, java, c++, java, python]
*/
public static void testLimit(List<String> list) {
/*
* limit 方法,是获取前num个元素
* 这里获取的就是前2个元素
* */
list.stream()
.limit(2)
.forEach(s -> System.out.println(s));
}
/**
* 测试 skip 方法
*
* @param list [c, java, c++, java, python]
*/
public static void testSkip(List<String> list) {
/*
* skip 方法,是跳过前num个元素
* 这里获取的就是前2个元素
* */
list.stream()
.skip(2)
.forEach(s -> System.out.println(s));
}
/**
* 去重方法
* 注意:这个方法依赖 equals 和 hashCode 方法,因为底层使用的是HashSet进行处理的
*
* @param list [c, java, c++, java, python]
*/
public static void testDistinct(List<String> list) {
list.stream()
.distinct()
.forEach(s -> System.out.println(s));
}
/**
* 合并流
* @param list [c, java, c++, java, python]
*/
public static void testConcat(List<String> list) {
List<String> list1 = new ArrayList<>();
Collections.addAll(list1, "开发语言", "测试");
Stream.concat(list.stream(),list1.stream()).forEach(s -> System.out.println(s));
}
}
2.3 Stream 中常用的终结方法
package cn.edu.njust.streamdemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Stream中常用的终结方法
*/
public class StreamDemo03 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(list, "c", "java", "c++", "java", "python");
// testForeach(list);
// testCount(list);
testToArray(list);
}
/**
* 遍历
* @param list [c, java, c++, java, python]
*/
public static void testForeach(List<String> list) {
list.stream().forEach(s -> System.out.println(s));
}
/**
* count 函数
* @param list [c, java, c++, java, python]
*/
public static void testCount(List<String> list) {
long count = list.stream().count();
System.out.println("count = " + count);
}
/**
* toArray
* @param list [c, java, c++, java, python]
*/
public static void testToArray(List<String> list) {
// 无参
Object[] array = list.stream().toArray();
System.out.println(Arrays.toString(array));
System.out.println("----------------");
// 有参构造
String[] array1 = list.stream().toArray(val -> new String[val]);
System.out.println(Arrays.toString(array1));
}
}
3 常用方法汇总
函数原因来自 JDK17
3.1 中间方法
流经过中间方法处理后不会关闭
** 方法原型** | **说明 ** |
---|---|
Stream filter(Predicate<? super T> predicate); | 过滤器 |
Stream limit(long maxSize); | 只获取前 limit 个元素 |
Stream skip(long n); | 跳过前面 n 个元素 |
public static Stream concat(Stream<? extends T> a, Stream<? extends T> b) | 合并两个流 |
3.2 终结方法
方法原型 | **说明 ** |
---|---|
void forEach(Consumer<? super T> action); | 遍历所有元素 |
Object[] toArray(); | 收集方法无参 |
A[] toArray(IntFunction<A[]> generator); | 收集方法有参 |
3.3 收集方法
这个视频讲得很清楚,主要讲解收集到 List,收集到 Set,收集到 Map
【黑马程序员Java零基础视频教程_下部(Java入门,含斯坦福大学练习题+力扣算法题和大厂java面试题)】
Stream流-05-收集方法collect超详解_哔哩哔哩_bilibili