Java8新特性 - Stream API
StreamAPI说明
Stream API 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
为什么要使用StreamAPI
-
实际开发中,项目中多数数据源都来自于Mysql, Oracle等。 但现在数据源可以更多了,有MongDB,Radis等, 而这些NoSQL的数据就需要Java层面去处理。
-
Stream和Collection集合的区别: Collection 是一种静态的内存数据
结构,而Stream是有关计算的。前者是主要面向内存,存储在内存中,
后者主要是面向CPU,通过CPU实现计算。
注意:
1.Stream自己不会存储元素。
2.Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream.
3.Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
4.一个中间操作链,对数据源的数据进行处理
5.一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
归约
package JAVA8.StreamAPI_;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class StreamUse05 {
@Test
public void test01(){
// reduce(T identity, BinaryOperator)- 可以将流中元素反复结合起来,得到一个值。返回T
// 练习1:计算1-10的自然数的和
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer reduce = list.stream().reduce(0, Integer::sum);//第一个参数为初始值,eg.如果为10,结果就是65
System.out.println(reduce);
// reduce(BinaryOperator)一可以将流中元素反复结合起来,得到一个值。返回Optional<T>
//计算所有员工工资的和
List<Employee> employees = EmployeeData.getEmployees();
Stream<Double> doubleStream = employees.stream().map(Employee::getSalary);
Optional<Double> reduce1 = doubleStream.reduce(Double::sum);
System.out.println(reduce1);
}
}
排序
package JAVA8.StreamAPI_;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StreamUse03 {
//sorted() 自然排序
@Test
public void test01() {
List<Integer> list = Arrays.asList(12, 43, 32, 67, 54, 87, 0, -98, 7);
list.stream().sorted().forEach(System.out::println);
}
//sorted(Comparator com) 定制排序
@Test
public void test02(){
List<Employee> employees = EmployeeData.getEmployees();
//按年龄排序
employees.stream().sorted((c1,c2) -> Integer.compare(c1.getAge(),c2.getAge())).forEach(System.out::println);
}
}
匹配和查找
package JAVA8.StreamAPI_;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class StreamUse04 {
@Test
public void test01(){
List<Employee> employees = EmployeeData.getEmployees();
//allMatch(Predicate p) 检查是否匹配所有元素
//eg.是否所有的人年龄都大于18
boolean b = employees.stream().allMatch(e -> e.getAge() > 18);
System.out.println(b?"全部大于18":"不是全部大于18");
//anyMatch(Predicate p) 检查是否至少匹配一个元素
//eg.是否存在工资大于10000的人
boolean b1 = employees.stream().anyMatch(e -> e.getSalary() > 10000);
// noneMatch(Predicate p)一检查是否没有匹配的元素!!。练习:是否存在员工姓“雷”
boolean w = employees.stream().noneMatch(e -> e.getName().contains("w"));
System.out.println(w);
// findFirst-返回第一个元素
Optional<Employee> first = employees.stream().findFirst();
System.out.println(first);
// findAny-返回当前流中的任意元素
Optional<Employee> any = employees.stream().findAny();
System.out.println(any);
// count-返回流中元素的总个数
long count = employees.stream().count();
System.out.println(count);
// max(Comparator c)-返回流中最大值
Optional<Employee> max = employees.stream().max((s1, s2) -> Integer.compare(s1.age, s2.age));
System.out.println(max);
// min(Comparator c)一 返回流中最小值
// 练习:返回最低工资的员工
Stream<Double> doubleStream = employees.stream().map(e -> e.getSalary());
Optional<Double> min = doubleStream.min(Double::compare);
System.out.println(min);
// forEach(Consumer c)- 内部迭代
employees.stream().forEach(System.out::println);
}
}
筛选和切片
package JAVA8.StreamAPI_;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Stream;
public class StreamUse01 {
// 一个中间操作链,对数据源的数据进行处理
// 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
//1.筛选与切片
@Test
public void test01(){
List<Employee> list = EmployeeData.getEmployees();
//filter(Predicate p) 接受lambda 从流中排除某些元素
Stream<Employee> stream = list.stream();
//查询员工表中工资大于7000的员工信息
stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println); // 必须有中间操作和终止操作才会执行
//执行后就会被销毁,不可以再用
System.out.println("****************");
//limit(n) 截断流,使其元素不超过给定元素数量
Stream<Employee> stream1 = list.stream();
// stream.limit(2).forEach(System.out::println); //再次使用销毁的stream会失效
stream1.limit(3).forEach(System.out::println);
System.out.println("******************");
//skip(n) 跳过元素,返回一个跳过了前n个元素后面的元素的流,若流中元素不足n,返回一个空流
Stream<Employee> stream2 = list.stream();
stream2.skip(2).forEach(System.out::println);
//distinct() 筛选,通过流所生成的元素的hashcode()和equal()去重
Stream<Employee> stream3 = list.stream();
stream3.distinct().forEach(System.out::println);
}
}
映射
package JAVA8.StreamAPI_;
import EE.Collection_.List_.list;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
public class StreamUse02 {
@Test
public void test01(){
List<Employee> employees = EmployeeData.getEmployees();
//map(Function f) 接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并映射成一个新元素
List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
strings.stream().map(String::toUpperCase).forEach(System.out::println);
//练习:获取员工姓名大于2的员工的姓名
employees.stream().map(Employee::getName).filter(e->e.length()>2).forEach(System.out::println);
//flatMap(Function f) 接受一个函数作为参数,将流中的每个值都换成另外一个流,然后把所有的流连成一个流
strings.stream().flatMap(new Function<String, Stream<?>>() {
@Override
public Stream<?> apply(String s) {
List list = new ArrayList();
for (Character c:
s.toCharArray()) {
list.add(c);
}
return list.stream();
}
}).forEach(System.out::println);
}
}
收集
package JAVA8.StreamAPI_;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Collectors;
public class StreamUse06 {
@Test
public void test01(){
//收集
// collect(Collector c)将流转换为其他形式。接收一一个Collector接口的实现,用于给Stream中元素做汇总的方法
//查询工资大于6000的人,结果返回一个List或Set
List<Employee> employees = EmployeeData.getEmployees();
List<Employee> collect = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
System.out.println(collect);
}
}