数据准备:
创建Employee类
package data;
import com.oracle.webservices.internal.api.databinding.DatabindingMode;
public class Employee {
private long id;
private String name;
private int age;
private double salary;
public Employee(long id,String name,int age,double salary){
this.id = id;
this.age = age;
this.name = name;
this.salary = salary;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString(){
return "Employee{"+"id="+id+",name="+name+",age="+age+",salary="+salary+"}";
}
}
创建EmployeeData类
package data;
import java.util.ArrayList;
import java.util.List;
public class EmployeeData {
public static List<Employee> getEmployees(){
List<Employee> list = new ArrayList<>();
list.add(new Employee(1001,"马化腾",34,6000.38));
list.add(new Employee(1002,"马云",2,9876.38));
list.add(new Employee(1003,"刘强东",33,3000.82));
list.add(new Employee(1004,"雷军",26,7657.37));
list.add(new Employee(1005,"李彦宏",65,5555.38));
list.add(new Employee(1006,"比尔盖茨",42,9500.38));
list.add(new Employee(1007,"任正非",34,4333.32));
list.add(new Employee(1008,"扎克伯格",35,2500.32));
return list;
}
}
1.创建Stream(三种方式)
package streamTest;
import data.Employee;
import data.EmployeeData;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class StreamAPITest {
//创建Stream方式一:通过集合
@Test
public void test1(){
List<Employee> list = EmployeeData.getEmployees();
//返回一个shuixu
Stream<Employee> stream = list.stream();
//返回一个并行流
Stream<Employee> stream1 = list.parallelStream();
}
//创建Stream方式二:通过数组
@Test
public void test2(){
//调用Arrays类的static<T> Stream<T> stream(T[] array):返回一个流
Integer[] arr = new Integer[]{1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(arr);
int[] arr1 = new int[]{1,2,3,4,5,6,7};
IntStream stream1 = Arrays.stream(arr1);
}
//创建Stream方式大三:通过Stream的of()
@Test
public void text3(){
Stream<String> stream = Stream.of("AA", "BB", "C");
}
}
2.一系列的在中间操作
1.筛选与切片
2.映射
3.排序
1.筛选与切片
package streamTest;
import data.Employee;
import data.EmployeeData;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Stream;
public class StreamAPITest1 {
//1-筛选与切片
@Test
public void test(){
//filter(Predicate p)——接收Lambda,从流中排除某些元素
//查询员工表中薪资大于7000的员工信息
List<Employee> list = EmployeeData.getEmployees();
System.out.println(list);
Stream<Employee> stream = list.stream();
stream.filter(emp -> emp.getSalary() > 7000).forEach(System.out::println);
System.out.println();
//limit(n)——截断流,使其元素不超过给定数量
//错误的。因为stream已经执行了终止操作,就不可以在调用其他的中间操作或终止操作了
// stream.limit(2).forEach(System.out::println);
list.stream().filter(emp -> emp.getSalary()>7000).limit(2).forEach(System.out::println);
// skip(n) ——跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,返回一个空流。
list.stream().skip(5).forEach(System.out::println);
}
}
注意:如果stream已经执行了终止操作,不可以在调用其他的中间操作或终止操作
2.映射
//2-映射
@Test
public void test2() {
//map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被映射到每个元素上
//转换为大写
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
//方式一:
list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
//方式二:
list.stream().map(String::toUpperCase).forEach(System.out::println);
//获取员工姓名长度大于3的员工
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().filter(employee -> employee.getName().length()>3).forEach(System.out::println);
//获取员工姓名长度大于3的员工的姓名
employees.stream().filter(employee -> employee.getName().length()>3).map(employee -> employee.getName()).forEach(System.out::println);
}
3.排序
//3-排序
@Test
public void test3(){
//sorted()——自然排序
Integer[] arr = new Integer[]{ 342,3,64,46,7,3,54,65,68};
String[] arr1 = new String[]{"GG","DD","MM","SS","JJ"};
Arrays.stream(arr).sorted().forEach(System.out::println);//arr数组并没有因为升序做调整
Arrays.stream(arr1).sorted().forEach(System.out::println);//arr数组并没有因为升序做调整
//因为Employee没有实现Comparable接口,所以报错!
// List<Employee> list = EmployeeData.getEmployees();
// list.stream().sorted().forEach(System.out::println);
//sorted(Comparator com)——定制排序
List<Employee> list = EmployeeData.getEmployees();
//升序
list.stream().sorted((e1,e2)-> e1.getAge()- e2.getAge()).forEach(System.out::println);
System.out.println();
//降序
list.stream().sorted((e1,e2)-> e2.getAge()- e1.getAge()).forEach(System.out::println);
//针对字符串从大到小
Arrays.stream(arr1).sorted((s1,s2)->s2.compareTo(s1)).forEach(System.out::println);
}
注意:Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream
3.终止操作
package streamTest;
import data.Employee;
import data.EmployeeData;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 终止操作
*/
public class StreamAPITest2 {
//1-匹配与查找
@Test
public void test(){
//是否所有的员工的年龄都大于18
//allMatch(Predicate p)——检查是否匹配所有元素
List<Employee> list = EmployeeData.getEmployees();
System.out.println(list.stream().allMatch(emp -> emp.getAge() > 18 ));
//是否存在年龄大于18岁的员工
//anyMatch(Predicate p)——检查是否至少匹配一个元素
System.out.println(list.stream().anyMatch(emp -> emp.getAge() > 18));
//是否存在员工的工资大于10000
System.out.println(list.stream().anyMatch(emp -> emp.getSalary() > 10000));
//findFirst——返回第一个元素
System.out.println(list.stream().findFirst().get());
}
@Test
public void test2(){
List<Employee> list = EmployeeData.getEmployees();
System.out.println(list.stream().filter(employee -> employee.getSalary()>7000).count());
//max(Comparator c)——返回流中的最大值
//返回最高工资的员工
System.out.println(list.stream().max((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())));
//返回最低的工资
//方式一:
System.out.println(list.stream().max((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())).get().getSalary());
//方式二:
System.out.println(list.stream().map(employee -> employee.getSalary()).max((e1,e2)->Double.compare(e1, e2)).get());
//min(Comparator c)——返回流中的最小值
//返回最低工资的员工
System.out.println(list.stream().min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())));
//forEach(Consumer c)——内部迭代
list.stream().forEach(System.out::println);
//针对于集合,jdk8中增加了一个遍历的方法
list.forEach(System.out::println);
}
//归约
@Test
public void test3(){
//reduce(T identity,BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回T
//计算1-10的自然数的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println(list.stream().reduce(0,(x1,x2)->x1+x2));
System.out.println(list.stream().reduce(10,(x1,x2)->x1+x2));
//reduce(BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回Optional<T>
//计算公司所有员工工资的和
List<Employee> employeeList = EmployeeData.getEmployees();
System.out.println(employeeList.stream().map(emp -> emp.getSalary()).reduce((salary1, salary2) -> Double.sum(salary1, salary2)));
}
@Test
public void test4(){
//collect(Collector c)——将流转换为其他形式。接受一个Collector接口的实现,用于给Stream中的元素做汇总的方法
//查找工资大于6000的员工,结果返回为一List或Set
List<Employee> list = EmployeeData.getEmployees();
List<Employee> list1 = list.stream().filter(emp -> emp.getSalary() > 6000).collect(Collectors.toList());
list1.forEach(System.out::println);
//按照员工的年龄进行排序,返回到一个新的List中
System.out.println();
List<Employee> list2 = list.stream().sorted((e1, e2) -> e1.getAge() - e2.getAge()).collect(Collectors.toList());
list2.forEach(System.out::println);
}
}
总结
1.程序运行中,流Stream只能使用一次,使用后会默认关闭,不能重复使用;重复使用会报错,信息如下:
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.spliterator(AbstractPipeline.java:343)
at java.util.stream.Stream.concat(Stream.java:1080)
2.在开发过程中,建议使用Stream.of(list),解决list为null的问题;使用list.stream()之前需要判断list是否为null,避免报错空指针异常(java.lang.NullPointerException)。
3.stream流遍历获取的对象是原对象
4.stream特性思维导图: