了解Stream
Java中有两大最为重要的改变。第一个是Lambda表达式;另外一个则是Stream API(java.util.stream.*)。
Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。
简而言之,Stream API提供了一种高效且易于使用的处理数据的方式。
什么是Stream
流(Stream)到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”
注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
Stream的三个操作步骤
1.创建Stream
2.中间操作
3.终止操作(终端操作)
创建Stream
Java8中的Collection接口被扩展,提供了两个获取流的方法:
default Stream Stream():返回一个顺序流
default Stream parallelStream():返回一个并行流
package StreamAPI;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.stream.Stream;
/*
* 一、Stream的三个操作步骤
* 1.创建Stream
* 2.中间操作
* 3.终止操作(终端操作)
*/
public class TestStreamAPI1 {
//创建Stream
@Test
public void test1(){
//可以通过Collection系列集合提供的stream()或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//可以通过Arrays中的静态方法stream()获取数组流
Stream<String> stream1 = Arrays.stream(new String[10]);
//通过Stream类中的静态方法of()
Stream<String> stream2 = Stream.of("wo","ai","chi","kao","ji");
//创建无限流
//迭代
Stream<Integer> stream3 = Stream.iterate(0,(x) -> x+5);
stream3.limit(10).forEach(System.out::println);
//生成
Stream<Double> stream4 = Stream.generate(() -> Math.random());
stream4.limit(10).forEach(System.out::println);
}
}
Stream的中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!
而在终止操作时一次性全部处理,称为“惰性求值”。
筛选与切片
映射
排序
示例
package StreamAPI;
import java.util.Objects;
enum Status{
FREE,
BUSY,
VOCATION;
}
public class Employee {
private String name;
private int age;
private double salary;
private Status status;
public Employee() {
}
public Employee(String name, int age, double salary, Status status) {
this.name = name;
this.age = age;
this.salary = salary;
this.status = status;
}
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;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
", status=" + status +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return age == employee.age &&
Double.compare(employee.salary, salary) == 0 &&
Objects.equals(name, employee.name) &&
status == employee.status;
}
@Override
public int hashCode() {
return Objects.hash(name, age, salary, status);
}
}
package StreamAPI;
import LambdaExpre.Employee;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
/*
* 一、Stream的三个操作步骤
* 1.创建Stream
* 2.中间操作
* 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
List<Employee> employees = Arrays.asList(
new Employee("张三",18,10000),
new Employee("赵六",30,5000),
new Employee("李四",24,15000),
new Employee("王五",14,8000),
new Employee("田七",29,7000)
);
//中间操作
/*
筛选与切片
filter -- 接收Lambda,从流中排除某些元素
limit -- 截断流,使其元素不超过给定数量
skip(n) -- 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
distinct -- 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
*/
//内部迭代:迭代操作由Stream API 完成
@Test
public void test1(){
//中间操作:不会执行任何操作
Stream<Employee> stream = employees.stream()
.filter((e) -> {
System.out.println("Stream API的中间操作");
return e.getAge() > 25;
});
//终止操作:一次性执行全部内容,即“惰性求值”
stream.forEach(System.out::println);
}
//外部迭代
@Test
public void test2(){
Iterator<Employee> iterator = employees.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test3(){
employees.stream()
.filter((e)->{
System.out.println("短路");
return e.getSalary()>6000;
})
.limit(2)//limit找到两个就不继续找了,短路,与&&、