黄河之水天上来,奔流到海不复回。Java中的流好比是河水,取值无尽,用之无竭,流是无尽的,我们通过流生成的元素进行复杂的计算。这里主要是记录一下使用方式,我们可以通过常用的数据结构创建流,并对数据进行筛选过滤,数据映射处理,后再进行数据的匹配输出,和通过使用for循环、调用函数方法等方式相比,该方式操作更加简洁、高效。

流的创建

我们可以通过集合、数组、字符串、文件流等方式创建流。

集合创建方式

通过Collection下的stream()和parallelStream()方法
🏳️‍🌈示例如下:
List list = new ArrayList<>();
Stream stringStream = list.stream();
Stream parallelStream = list.parallelStream();

数组创建方式

🏳️‍🌈示例如下
Integer[] nums = new Integer[10];
Stream stream = Arrays.stream(nums);

Stream中的静态方法

使用of方法
Stream stream = Stream.of(1,2,3,4,5);
使用iterate方法
Stream stream2 = Stream.iterate(0,(x)->x+2).limit(6);
使用generate方法
Stream stream3 = Stream.generate(Math::random).limit(2);

文件流的创建方式

使用BufferedReader.lines() 中的静态方法
BufferedReader reader = new BufferedReader(new FileReader("F:\test_stream.txt"));
Stream lineStream = reader.lines();
lineStream.forEach(System.out::println);

字符串方式创建流

使用Pattern.splitAsStream()方法,将字符串分割成流
Pattern pattern = Pattern.compile(",");
Stream stringStream = pattern.splitAsStream("a,b,c,d");
stringStream.forEach(System.out::println);

流的中间操作

将数据结构转换为流,我们可以对流上的数据进行处理,处理方式包括数据筛选,排序,以及通过函数进行映射操作。个人觉得这也是流的好处之一,通过该方式简化了很多冗余的代码编写。

筛选与切片

通过该方式实现简单的数据操作

过滤(filter)

Stream stream = Stream.of(6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14);
Stream newStream = stream.filter(s->s>5);
newStream.forEach(System.out::println);

去重(distinct)

Stream stream = Stream.of(6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14);
Stream newStream = stream.distinct();
newStream.forEach(System.out::println);

获取n个元素

Stream stream = Stream.of(6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14);
Stream newStream = stream.limit(3);
newStream.forEach(System.out::println);

跳过n个元素

Stream stream = Stream.of(6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14);
Stream newStream = stream.skip(3);
newStream.forEach(System.out::println);

映射

通过流进行函数映射转换。

Map

map:接收一个函数作为参数,该函数将映射到每一个元素上,将其映射成为一个新的元素
List list = Arrays.asList("a,b,c","1,2,3");
Stream s1 = list.stream().map(s->s.replaceAll(",",""));
s1.forEach(System.out::println);

Peek

Peek:如同map,但是没有返回值
Student s1 = new Student("aa", 10);
Student s2 = new Student("bb", 20);
List studentList = Arrays.asList(s1, s2);

studentList.stream() .peek(o -> o.setAge(100)).forEach(System.out::println);
//结果:
Student{name='aa', age=100}
Student{name='bb', age=100}

flatMap

flatMap:接受一个函数作为参数,将流中的每个值都换成另一个流,并将所有的流连接
List list = Arrays.asList("a,b,c","1,2,3");
Stream s4 = list.stream().flatMap(s->{String[] split = s.split(",") Stream s2 = Arrays.stream(split);
return s2; });
s4.forEach(System.out::println);

排序

通过流实现数据结构的排序

自然排序

自然排序,流中的元素需要实现Comparable接口
List list = Arrays.asList("aa","ff","dd");
list.stream().sorted().forEach(System.out::println);

定制排序

定制排序,自定义Comparator排序器
Student s1 = new Student("aa", 10);
Student s2 = new Student("bb", 20);
Student s3 = new Student("aa", 30);
Student s4 = new Student("dd", 40);
List studentList = Arrays.asList(s1, s2, s3, s4);
//自定义排序:先按姓名升序,姓名相同则按年龄升序
studentList.stream().sorted(
(o1, o2) -> {
if (o1.getName().equals(o2.getName())) {
return o1.getAge() - o2.getAge();
} else {
return o1.getName().compareTo(o2.getName());
}
}
).forEach(System.out::println);

流的终止操作

通过流进行了数据的中间操作后,需要通过流进行匹配输出

匹配操作

allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false

聚合操作

findFirst:返回流中第一个元素
findAny:返回流中的任意元素
count:返回流中元素的总个数
max:返回流中元素最大值
min:返回流中元素最小值

规约操作

相当于是循环操作执行,如1,2,3,4,5.则为1+2,3+3,6+4.....

收集操作

接收一个Collector实例,将流中元素收集成另外一个数据结构
//装成list
List ageList = list.stream().map(Student::getAge).collect(Collectors.toList()); // [10, 20, 10]