文章目录
来源:https://www.toutiao.com/i6770603570233344524/
本文根据来源整理
Stream
一、Stream是什么?
从名字来看,Stream就是一个流,他的主要作用就是对集合数据进行查找过滤等操作。有点类似于SQL的数据库操作。一句话来解释就是一种高效且易用的数据处理方式。
大数据领域也有一个Steam实时流计算框架,不过和这个可不一样。别搞混了。举个例子吧,比如 说有一个集合Student数据,我们要删选出学生名字为“张三”的学生,或者是找出所有年龄大于18岁的所有学生。此时我们就可以直接使用Stream来筛选。当然了这只是给出了其中一个例子。Stream还有很多其他的功能。Stream和Collection的区别就是:Collection只是负责存储数据,不对数据做其他处理,主要是和内存打交道。但是Stream主要是负责计算数据的,主要是和CPU打交道。现在明白了吧。
二、Stream语法讲解
Stream执行流程很简单,主要有三个,首先创建一个Stream,然后使用Stream操作数据,最后终止Stream。有点类似于Stream的生命周期。下面我们根据其流程来一个一个讲解。
1、前提准备
首先我们创建一个Student
类,以后我们每次都是操作这个类
/**
* @author xiao
* @date 6/13/2020 7:41 PM
*/
@NoArgsConstructor @AllArgsConstructor @Data
public class Student{
private Integer id;
private String name;
private Integer age;
private Double score;
}
然后下面我们再创建一个``StudentData`类,用于获取其数据
/**
* @author xiao
* @date 6/13/2020 7:49 PM
*/
public class StudentData {
public static List<Student> getStudents() {
List<Student> list = new ArrayList<>();
list.add(new Student(3, "张三", 18, 90.4));
list.add(new Student(4, "李四", 19, 85.2));
list.add(new Student(5, "王五", 21, 75.1));
list.add(new Student(6, "赵六", 15, 81.4));
list.add(new Student(7, "钱七", 16, 92.3));
list.add(new Student(8, "孙八", 19, 96.5));
list.add(new Student(9, "杨九", 24, 57.3));
list.add(new Student(10, "吴十", 268, 60.7));
return list;
}
}
2、创建Stream
方式一:通过一个集合创建Stream
/**
* 通过集合 创建Stream
*
* @see List#stream()
* @see List#parallelStream()
*/
@Test
public void test1() {
List<Student> studentList = StudentData.getStudents();
// 第一种:返回一个顺序流
Stream<Student> stream1 = studentList.stream();
// 第二种:返回一个并行流
Stream<Student> stream2 = studentList.parallelStream();
}
方式二:通过一个数组创建Stream
/**
* 通过数组 创建一个Stream
*
* @see Arrays#stream(Object[])
* @see Arrays#stream(Object[], int, int) 左闭右开
*/
@Test
public void test2() {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 获取一个整形的Stream
IntStream intStream = Arrays.stream(arr, 0, arr.length);
intStream = Arrays.stream(arr);
System.out.println(intStream);
}
方式三:通过Stream.of
/**
* 方式三:通过Stream.of
*
* @see Stream#of(Object)
* @see Stream#of(Object[])
*/
@Test
public void test3() {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 5, 6, 7, 8);
Stream<String> stringStream = Stream.of("1", "2", "3", "5", "6", "7", "8");
Stream<Student> studentStream = Stream.of(
new Student(3, "张三", 18, 90.4),
new Student(3, "张三", 18, 90.4),
new Student(3, "张三", 18, 90.4));
}
方式四:创建一个无限流
/**
* 创建一个无限流
*/
@Test
public void test4() {
//每隔5个数取一个,从0开始,此时就会无限循环
Stream.iterate(0, t -> t + 5).forEach(System.out::println);
//每隔5个数取一个,从0开始,只取前5个数
Stream.iterate(0, t -> t + 5).limit(5).forEach(System.out::println);
//取出一个随机数
Stream.generate(Math::random).limit(5).forEach(System.out::println);
}
3、使用Stream操作数据
操作1:筛选和切片
/**
* 筛选和切片
* @see Stream#filter(Predicate) 过滤
* @see Stream#limit(long) 限制
* @see Stream#skip(long) 跳过前几个
* @see Stream#forEach(Consumer) 遍历消费
*/
@Test
public void test1() {
List<Student> list = StudentData.getStudents();
System.out.println("filter -----");
list.stream().filter(item -> item.getAge() > 20)
.forEach(System.out::println);
System.out.println("limit 3-----");
list.stream().limit(3).forEach(System.out::println);
System.out.println("skip 5 -----");
list.stream().skip(7).forEach(System.out::println);
System.out.println("distinct -----");
list.stream().distinct().forEach(System.out::println);
}
操作2:映射
/**
* 映射
* @see Stream#map(Function)
*/
@Test
public void test2(){
List<String> list = Arrays.asList("java", "python", "go");
Stream<String> stream = list.stream();
stream.map(String::toUpperCase).forEach(System.out::println);
List<Student> students = StudentData.getStudents();
Stream<Student> stream1 = students.stream();
Stream<Integer> ageStream =stream1.map(Student::getAge);
ageStream.filter(age -> age > 20).forEach(System.out::println);
}
操作3:排序
/**
* 排序
* @see Stream#sorted()
* @see Stream#sorted(Comparator)
*/
@Test
public void test3(){
List<Integer> list = Arrays.asList(4,3,6,1,7,18,9,12,31,0,1);
Stream<Integer> stream = list.stream();
stream.sorted().forEach(System.out::println);
List<Student> studentList = StudentData.getStudents();
studentList.stream().sorted(Comparator
.comparingInt(Student::getAge))
.forEach(System.out::println);
}
4、终止Stream
操作1:匹配和查找
/**
* 匹配和查找
*/
@Test
public void test1() {
List<Student> list = StudentData.getStudents();
boolean allMatch = list.stream().allMatch(item -> item.getAge() > 20);
boolean anyMatch = list.stream().anyMatch(item -> item.getAge() > 20);
boolean noneMatch = list.stream().noneMatch(item -> item.getAge() > 20);
Optional<Student> first = list.stream().findFirst();
System.out.println(first.get());
// 查找不同学生的数量
long count = list.stream().distinct().count();
long count1 = list.stream().filter(item -> item.getAge() > 20).count();
// 查找当前流中的元素
Optional<Student> any = list.stream().findAny();
System.out.println(any.get());
Stream<Double> doubleStream = list.stream().map(Student::getScore);
Optional<Double> max = doubleStream.max(Double::compare);
}
操作2:归约
/**
* 归约
*/
@Test
public void test2() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
// 计算学生总分
List<Student> studentList = StudentData.getStudents();
Stream<Double> doubleStream = studentList.stream().map(Student::getScore);
Optional<Double> reduce1 = doubleStream.reduce(Double::sum);
System.out.println(reduce1.orElse(0.0));
}
操作3:收集
/**
* 收集
*
* @see Stream#collect(Collector)
* <b>这里是Collector不是Collection</b>
*
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@Test
public void test3() {
List<Student> studentList = StudentData.getStudents();
// 返回一个list
List<Student> collect = studentList.stream()
.filter(e -> e.getAge() > 10)
.collect(Collectors.toList());
// 返回一个set
Set<Student> collectSet = studentList.stream()
.filter(e -> e.getAge() > 10)
.collect(Collectors.toSet());
// Collectors.toMap()
}
stream基本的语法就是这样,你会发现Stream就像是一个工具一样,可以帮我们分析处理数据,极其的好用,但是目前还不知道其效率如何。根据网上一位大佬的内存时间分析,其实在数据量比较庞大的时候,Stream可以为我们节省大量的时间,数据量小的时候并不明显。