Java8中最重要的两个改变一个是Lambda表达式,一个则是Stream API
Stream API(java.util.stream)把真正的函数式编程风格引入Java中,这是目前为止Java类库最好的补充,因为Stream API可以极大的提供Java程序员的生产力,让程序员写出更高效、干净、优美、简洁的代码。
Stream 是Java8中处理集合的关键概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于SQL执行数据库的查询。也可以使用Stream API来并行操作。简而言之,Stram API 提供了一种高效且易于使用的处理数据的方式。
持久层数据库,比如Mysql、Oracle等,相当于是在数据库层面进行数据的操作,但是随着MongDB、Radis等NoSQL数据库的出现,就需要在Java层面进行数据的操作了。这个时候使用Steam API
Stream 和 Collection 集合的区别:Collection是一种静态的内存结构。而Stream是有关计算的。前者主要是面向内存,存储在内存中,后者主要是面向CPU,案通过CPU实现计算。
集合将的是数据,Stream讲的是计算。
(1)Stream自己不会存储元素。
(2)Stream不会改变源对象,相反他们会返回一个持有结果到新的Stream中。
(3)Stream操作是延迟执行的,这意味着他们会等到需要结果的时候才执行。
一个数据源(如:集合、数组),获取一个流
@Test
public void test(){
//获取一个集合
List<Employee> list = EmplpyeeData.getEmployees();
//default Stream stream(); 返回一个顺序流
Stream<Employee> stream = list.stream();
//default Stream parallelStream(); 返回一个并行流
Stream<Employee> parallelStream = list.parallelStream();
}
@Test
public void test(){
int[] arr = new int[]{
1,2,3,4,5,6};
//调用Arrays类的static Stream stream(T[] array);返回一个流
Instream stream = Arrays.stream(arr);
Employee e1 = new Employee("1001","Tom");
Employee e2 = new Employee("1002","Marry");
Employee[] arr1 = new Employee[]{
e1,e2};
Stream<Employee> stream1 = Arrays.stream(arr1);
}
@Test
public void test(){
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
}
@Test
public void test(){
//迭代
//public static Stream iterate(final T seed,final UnaryOperator f);
//遍历前10个偶数(不会停下来)
Stream.iterate(0,t -> t + 2).forEach(System.out::println);
//加上限制,只要前十个偶数
Stream.iterate(0,t -> t + 2)limit(10).forEach(System.out::println);
//生成
//public static Stream generate(Supplier s);
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
一个中间操作链,对数据源的数据进行处理。
@Test
public void test(){
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);
//截断流 注意需要冲洗生成流,因为之前已经进行了终止操作
//是元素不超过给定的数量
list.stream().limit(3).forEach(System.out::println);
//skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个Null
list。stream().skip(20).forEach(System.out::println);
//distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
list.stream().distinct().forEach(System.out::println);
}
@Test
public void test13(){
List<String> list = Arrays.asList("abc","def","cbd","aaa");
//map(Function f) 接收一个函数作为参数,该函数提供了某种规则,通过这种规则将原有集合的数据映射到一个新的集合中。
list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
//练习:获取员工姓名大于三的员工姓名
List<Emplouyee> list = employeeData.getEmplyees();
//Stream nameStream = list.stream.map(e -> e.getName());
Stream<String> nameStream = list.stream.map(Employee :: getName);
nameStream.filter(name ->name.length()>3).forEach(System.out::println);
}
@Test
public void test(){
//flatMap(Function f) 接受一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流。
//练习:
//集合里面套集合的情况时,遍历每一个元素。
//用map来做
//注意:StreamAPITest是类名,使用类名::静态方法
Stream<Stream<Charcator>> streamStream = list.stream().map(StreamAPITest :: fromStringtoStream);
streamStream.forEach(s ->{
s.forEach(System.out::println)
});
//用flatMap来做
Stream<Charactor> charactorStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);
charactorStream.forEach(System.out::println);
}
public static Stream<Charcater> fromStringToStream(String str){
ArrayList<Character> list = new ArrayList<>();
for(Charactor c : str.toCharArray()){
list.add(c);
}
return list.stream();
}
@Test
public void test(){
//sorted() 自然排序
List<Integer> list = Arrays.asList(1,2412,3423,54,3234,645,1,212,-13,11);
list.stream().sorted().forEach(System.out::println);
//对象的排序,sorted(Comparator com) 定制排序
//需要实现接口
List<Employee> list = employeeData.getEmployees();
list.stream().sorted((e1,e2) -> {
int ageValue = Integer.compare(e1.getAge(),e2.getAge());
//按照年龄进行排序,如果年龄相等按照工资进行排序
if(ageValue != 0){
return ageValue;
}else{
return - Double.compare(e1.getSalary(),e2.getSalary());
}
}).forEach(System.out::println);
}
一旦执行终止操作,就执行中间操作链,并产生结果,之后,不会再被使用。如果想再用需要重新创建一个Stream流
List<Employee> list = EmployeeData.getEmployees();
//allMatch(Predicate p) 检查是否匹配所有元素
//练习:是否所有员工的年龄都大于18
boolean allMatch = list.stream().allMatch(e -> e.getAge() > 18);
//anyMatch(Predicate p) 检查是否至少匹配一个元素。
//练习:是否存在员工的工资大于10000
boolean anyMatch = list.stream().anyMatch(e -> e.getSalary() > 10000);
//noneMatch(Predicate p) 检查是否没有匹配的元素,有返回false,没有返回true
//练习:是否存在员工姓”雷“
boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startWitch("雷"));
//findFirst()返回第一个元素,可以结合排序来写
//findAny() 返回当前流中的任意元素
//count() 返回流中元素的总个数
long count = list.stream().filte(e -> e.getSalary() > 5000).count();
//max(Comparator c) 返回流中最大值
//练习 求员工中最高工资
//使用map先映射到工资...
Stream<Double> salaryStream = employees.stream().map(e - >e.getSalary());
Optional<Double> maxSalary = salarySaream.max(Double :: compare);
//min(Comparator c) 返回流中最小值
//求最低工资的员工信息
Optional<Employee> employee = list.stream().min((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary()));
//forEach(Cousumer c) 内部迭代
list.stream().forEach(System.out::println);
//注意与集合中的forEach()进行区分
list.forEach(System.out::println);
@Test
public void test14(){
//T reduce(T identity, BinaryOperator accumulator); 可以将流中元素反复结合起来,得到一个值,返回一个T
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
//Optional reduce(BinaryOperator accumulator); 可以将流中元素反复结合起来得到一个值,返回Optional
//计算公司中所有员工工资的总和
List<Employee> list = EmployeeData.getEmployees();
Stream<Double> salaryStream = list.stream().map(Employee :: getSalary);
Optional<Employee> countMoney = salaryStream.reduce(Double :: sum);
//或者也可以自己写累加
Optional<Employee> countMoney = salaryStream.reduce((d1,d2) -> d1 + d2);
}
@Test
public void test(){
//collect(Collector c) 将流转化为其他形式,接收一个Collector接口的实现,用于
List<Employee> list = EmployeeData.getEmployees();
//将工资中大于6000的放到一个list中
List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
employeeList.forEach(System.out::println);
//也可以放到一个set集合中,只需要调用Collectors中写好的静态方法就可以了
List<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
employeeSet.forEach(System.out::println);
}