一、Stream 流
1.1 概念
官方解释:可以支持顺序和并行对元素操作的元素集合。
简单来讲,Stream 就是 JDK8 提供给我们的对于元素集合统一、快速、并行操作的一种方式。
它能充分运用多核的优势,以及配合 Lambda 表达式、链式结构对集合等进行许多有用的操作。
1.2 特征
- Pipelining: 所有中间操作都会返回流对象本身,这样多个操作可以串联成一个管道。
- 内部迭代: 通过
Iterator
或者增强for
的形式在集合外部进行迭代的操作叫做外部迭代,而Stream
提供了内部迭代的方法,流可以直接调用遍历方法。
当使用一个流的时候,通常需要三个步骤:
获取数据源 --> 数据转换 --> 执行操作
每次转换操作时,原有的 Stream 对象不改变,返回一个新的 Stream对象。
二、获取流
java.util.stream.Stream<T>
是 Jdk 8 新添加的流接口(并不是一个函数式接口),通常有以下几种常用方式:
- 所有的
Collection
集合都可以通过Stream
默认方法获取流; Stream
接口的静态方法of
可以获取数组对应的流。
2.1 根据 Collection 获取流
public class DemoGetStream {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<>();
Stream<String> setStream = set.stream();
}
}
2.2 根据 Map 获取流
public class DemoGetStream {
public static void main(String[] args) {
Map<String,Object> map = new HashMap<>();
Stream<String> keyMapStream = map.keySet().stream();
Stream<Object> valueMapStream = map.values().stream();
Stream<Map.Entry<String, Object>> entryStream = map.entrySet().stream();
}
}
2.3 根据数组获取流
public class DemoGetStream {
public static void main(String[] args) {
String[] strArray = {"a","b","c"};
Stream<String> strStream= Stream.of(strArray);
Integer[] intArray = {1,2,-3,44,100};
Stream<Integer> intStream= Stream.of(intArray);
}
}
三、常用方法
Stream
有很多操作方法,分为两种类型:
- 延迟方法: 返回值类型仍然是
Stream
接口自身类型的方法,因此支持链式调用。 - 终结方法: 返回值类型不再是
Stream
接口自身类型的方法,因此不支持链式调用。
方法名称 | 方法类型 | 作用 | 方法含义 |
---|---|---|---|
forEach | 终结方法 | 循环 | 接收一个 Consumer 对象,将每一个流元素交给该函数进行处理 |
filter | 延迟方法 | 过滤 | 接收一个 Predicate 对象 作为筛选条件,将一个流筛选为另一个流 |
map | 延迟方法 | 映射 | 接收一个 Function 对象,将当前流中的 T 类型数据转换为 R 类型的流 |
count | 终结方法 | 统计 | 统计流中的个数 |
limit | 延迟方法 | 取前几个对象 | 对流进行截取,只取前 N 个对象 |
skip | 延迟方法 | 跳过前几个对象 | 对流进行截取,跳过前 N 个对象 |
concat | 延迟方法 | 组合 | 将两个流合并成一个流 |
3.1 forEach 方法
格式:
void forEach(Consumer<? super T> action);
实例:
public class DemoStreamForEach {
public static void main(String[] args) {
Stream<String> stream = Stream.of("三国演义","红楼梦","西游记","三字经");
stream.forEach(s -> System.out.println(s));
}
}
3.2 filter 方法
格式:
Stream<T> filter(Predicate<? super T> predicate);
实例:
public class DemoStreamFilter {
public static void main(String[] args) {
Stream<String> stream = Stream.of("三国演义", "红楼梦", "西游记", "三字经");
stream
.filter(s -> s.contains("三"))
.forEach(s -> System.out.println(s));
}
}
3.3 map 方法
格式:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
实例:
public class DemoStreamMap {
public static void main(String[] args) {
Stream<String> stream = Stream.of("10", "2", "33");
Stream<Integer> integerStream = stream.map(s -> Integer.parseInt(s));
}
}
3.4 count 方法
格式:
long count();
实例:
public class DemoStreamCount {
public static void main(String[] args) {
Stream<String> stream = Stream.of("三国演义", "红楼梦", "西游记", "三字经");
System.out.println(stream.count());
}
}
3.5 limit 方法
格式:
Stream<T> limit(long maxSize);
实例:
public class DemoStreamLimit {
public static void main(String[] args) {
Stream<String> stream = Stream.of("三国演义", "红楼梦", "西游记", "三字经");
stream
.limit(3)
.forEach(s -> System.out.println(s));
}
}
3.6 skip 方法
格式:
Stream<T> skip(long n);
实例:
public class DemoStreamSkip {
public static void main(String[] args) {
Stream<String> stream = Stream.of("三国演义", "红楼梦", "西游记", "三字经");
stream
.skip(3)
.forEach(s -> System.out.println(s));
}
}
3.7 concat 方法
格式:
static <T> Stream<T> concat(Stream<? extends T> a,Stream<? extends T> b);
实例:
public class DemoStreamConcat {
public static void main(String[] args) {
Stream<String> chinaBooksStream = Stream.of("三国演义", "红楼梦", "西游记", "三字经");
Stream<String> foreignBooksStream = Stream.of("悲惨世界", "哈里波特");
Stream
.concat(chinaBooksStream, foreignBooksStream)
.forEach(s -> System.out.println(s));
}
}