StreamAPl说明
●Java8中有两大最为重要的改变。第-一个是Lambda表达式:另外一个则
是Stream API。
●Stream API ( java. util.stream)把真正的函数式编程风格引入到Java中。这
是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程
序员的生产力,让程序员写出高效率、干净、简洁的代码。
●Stream 是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进
行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用
Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。
也可以使用Stream API来并行执行操作。简言之,StreamAPl 提供了一种
高效且易于使用的处理数据的方式。
●实际开发中,项目中多数数据源都来自于Mysq|l, Oracle等。 但现在数
据源可以更多了,有MongDB,Radis等, 而这些NoSQL的数据就需要
Java层面去处理。
●Stream 和Collection集合的区别: Collection 是一种静态的内存数据
结构,而Stream是有关计算的。前者是主要面向内存,存储在内存中,
后者主要是面向CPU,通过CPU实现计算。
Stream到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,Stream讲的是计算!”
注意:
①Stream自己不会存储元素。
②Stream不会改变源对象。相反,他们会返回一-个持有结果的新Stream.
⑧Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
使用
- Stream关注的是对数据的运算,与CPU打交道
集合关注的是数据的存储,与内存打交道
2.aStream自己不会存储元素。
Stream不会改变源对象。相反,他们会返回-个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
3.Stream执行流程
①Stream的实例化
②一系列的中间操作(过滤、映射、…)
③终止操佾
4.说明:
4.1一个中间操作链,对数据源的数据进行处理
4.2 - -旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
package com.changxiong.StreamTest;
import java.util.Objects;
/**
* @author changxiong
* @create 2020-12-14-11:18 PM
*/
public class Employee {
private String id;
private String name;
private Integer age;
private Integer salary;
public Employee() {
}
public Employee(String id) {
this.id = id;
}
public Employee(String id, String name) {
this.id = id;
this.name = name;
}
public Employee(String id, String name, Integer age, Integer salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSalary() {
return salary;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return Objects.equals(id, employee.id) &&
Objects.equals(name, employee.name) &&
Objects.equals(age, employee.age) &&
Objects.equals(salary, employee.salary);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age, salary);
}
}
package com.changxiong.StreamTest;
import java.util.ArrayList;
import java.util.List;
/**
* @author changxiong
* @create 2020-12-15-2:41 PM
*/
public class EmployeeData {
public static List<Employee> getEmployees() {
List<Employee> list = new ArrayList<>();
list.add(new Employee("1001","小明",40,100));
list.add(new Employee("1002","小白",50,101));
list.add(new Employee("1003","小黑",60,102));
list.add(new Employee("1004","虎妹",70,103));
list.add(new Employee("1005","卡喵",80,104));
list.add(new Employee("1006","花花",90,105));
list.add(new Employee("1007","小咕噜",120,106));
list.add(new Employee("1008","小憨包",130,107));
list.add(new Employee("1009","白居居",140,109));
return list;
}
}
package com.changxiong.StreamTest;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
* @author changxiong
* @create 2020-12-15-2:51 PM
*/
public class StreamDemo {
/**
* 创建Stream方式二: 通过数组。
* Java8中的Arrays的静态方法stream()可以获取数组流:
* ●static <T> Stream<T> stream(T0 array):返回-一个流
* 重载形式,能够处理对应基本类型的数组:
* ●public static IntStream stream(int[] array)
* ●public static LongStream stream(longD array)
* ●public static DoubleStream stream(double[] array)
*/
@Test
public void test1() {
List<Employee> list = EmployeeData.getEmployees();
//创建一个顺序流
Stream<Employee> stream = list.stream();
//创建一个并行流
Stream<Employee> listParallel = list.parallelStream();
}
@Test
public void test2() {
int[] arr=new int[]{1,2,3,4,5,6};
IntStream stream = Arrays.stream(arr);
Employee e1 = new Employee("1001", "Tom");
Employee e2 = new Employee("1002", "Mery");
Employee[] arr1=new Employee[]{e1,e2};
Stream<Employee> stream1 = Arrays.stream(arr1);
}
/**
* 。创建Stream方式三:通过Stream的of()
* 可以调用Stream类静态方法of(),通过显示值创建-一个
* 流。它可以接收任意数量的参数。
* ●public static<T> Stream<T> of(T.. values):返回一个流
*/
@Test
public void test3() {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);
Stream<String> s = Stream.of("a", "b", "c");
}
@Test
public void test4() {
//迭代
// public static <T>Stream<Integer> iterate(Integer seed, UnaryOperator<Integer> f)
// unaryOperator 传入一个类型,返回一个同类型的值
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
System.out.println();
//生成
//public static <T> Stream<T> generate(@NotNull java.util.function.Supplier<T> s)
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
//====================================Stream的中间件==============================
/**
* Stream的中间操作。
* 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止
* 操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全
* 部处理,称为“惰性求值”
* 1-筛选与切片
* 方法
* 描述
* filter(Predicate p)
* 接收Lambda,从流中排除某些元素
* distinct()
* 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
* limit(long maxSize)截断流, 使其元素不超过给定数量
* 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一
* skip(long n)
* 个空流。与limit(n)互补
*/
@Test
public void test5() {
//filter(redicate p)排除某些元素
List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> stream = employees.stream();
stream.filter(e->e.getAge()>50).forEach(e-> System.out.println(e.getName()));
System.out.println("============");
//limit(n) 截断流 元素不超过指定个数
employees.stream().limit(10).forEach(e-> System.out.println(e.getName()));
System.out.println();
//skip 跳过元素
employees.stream().skip(3).forEach(System.out::println);
System.out.println();
//distinct 去重 需要重写对象的hashCode和equal方法才能去重
employees.add(new Employee("1012","虎妹",40,100));
employees.add(new Employee("1012","虎妹",40,100));
employees.add(new Employee("1012","虎妹",40,100));
employees.add(new Employee("1012","虎妹",40,100));
employees.add(new Employee("1012","虎妹",40,100));
employees.add(new Employee("1012","虎妹",40,100));
employees.stream().distinct().forEach(System.out::println);
}
//=========================================中间操作 之 映射========================================
@Test
public void test6() {
//map(Function)
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.stream().map(s->s.toUpperCase()).forEach(System.out::println);
System.out.println();
//获取员工名称长度为3的员工
List<Employee> employees = EmployeeData.getEmployees();
Stream<String> streamMap = employees.stream().map(Employee::getName);
streamMap.filter(s->s.length()>=3).forEach(System.out::println);
//练习
Stream<Stream<Character>> streamStream = list.stream().map(StreamDemo::fromToString);
streamStream.forEach(s->s.forEach(System.out::println));
System.out.println();
Stream<Character> characterStream = list.stream().flatMap(StreamDemo::fromToString);
characterStream.forEach(System.out::println);
}
public static Stream<Character> fromToString(String str) {
ArrayList<Character> list = new ArrayList<>();
char[] chars = str.toCharArray();
for (char aChar : chars) {
list.add(aChar);
}
return list.stream();
}
//=========================================中间操作 之 排序========================================
@Test
public void test7() {
List<Integer> list = Arrays.asList(10, 23, 45, 23, 28, 84, 9, 10, 83, 45);
list.stream().sorted().forEach(System.out::println);
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().sorted((e1,e2)->Integer.compare(e1.getAge(),e2.getAge()))
.forEach(System.out::println);
System.out.println();
employees.stream().sorted(
(e1,e2)->{
int ageValue = Integer.compare(e1.getAge(), e2.getAge());
if (ageValue!=0){
return ageValue;
}else{
int salaryValue = Integer.compare(e1.getSalary(), e2.getSalary());
return salaryValue;
}
}
).forEach(System.out::println);
}
//===============Stream终止符===================
@Test
public void test8() {
//是否匹配所有元素 allmatch(predicate p)
//是否所有员工年龄都大于18
List<Employee> employees = EmployeeData.getEmployees();
boolean b = employees.stream().allMatch(e -> e.getAge() > 18);
System.out.println(b);
System.out.println();
//anyMath(predicate p )至少匹配一个
boolean b1 = employees.stream().anyMatch(e -> e.getAge() > 18);
System.out.println(b1);
System.out.println();
//noneMatch(predicate p) 没有匹配的
boolean b2 = employees.stream().noneMatch(e -> e.getAge() > 10);
System.out.println(b2);
System.out.println();
}
@Test
public void test9() {
List<Employee> employees = EmployeeData.getEmployees();
//返回第一个元素 findFirst
Optional<Employee> employee = employees.stream().findFirst();
System.out.println(employee);
System.out.println();
//返回任意一个对象 findany
Optional<Employee> any = employees.stream().findAny();
System.out.println(any);
System.out.println();
//返回流中元素统计数量 count
long count = employees.stream().filter(e -> e.getSalary() > 100).count();
System.out.println(count);
System.out.println();
//max(comparator c) 返回流中元素最大值
//返回员工工资最高的
Stream<Integer> salaryStream = employees.stream().map(e -> e.getSalary());
Optional<Integer> max = salaryStream.max(Double::compare);
System.out.println(max);
System.out.println();
//min(comparator c)返回流中最小值 返回年龄最小的
Stream<Integer> ageStream = employees.stream().map(e -> e.getAge());
Optional<Integer> min = ageStream.min(Integer::compare);
System.out.println(min);
System.out.println();
//foreach 内部遍历
employees.stream().forEach(e-> System.out.println(e.toString()));
}
//--------------终止 之 规约----------------------
@Test
public void test10() {
//reduce(T identify,BinaryOperator p) 归约 将流中的值反复结合起来得到一个值
//第一个参数是传入的参数 第二个是function的子类
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 5, 6, 7, 8, 9);
Integer max = list.stream().reduce(0, Integer::sum);
System.out.println(max);
System.out.println();
//reduce(binaryoperator)
//计算员工工资总和
Stream<Integer> integerStream = EmployeeData.getEmployees().stream().map(e -> e.getSalary());
Optional<Integer> reduce = integerStream.reduce(Integer::sum);
System.out.println(reduce);
}
//================终止操作 之 收集
@Test
public void test11() {
//collect(collector c)
//查找工资大于103 返回一个list或者set集合
List<Employee> collect = EmployeeData.getEmployees().stream().filter(e -> e.getSalary() > 103).collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println();
Set<Employee> collect1 = EmployeeData.getEmployees().stream().filter(e -> e.getSalary() > 103).collect(Collectors.toSet());
collect1.forEach(System.out::println);
}
}
排序
终止