Stream 是java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作, 可以执行非常复杂的查找,过滤,映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。 简而言之,Stream API提供了一种高效且易于使用的处理数据的方式。 为什么要使用Stream API? 实际开发中,有许多数据源来自mysql oracle等关系型数据库,随着现在应用场景的需要,MongDB REDIS这样nosql数据库也用得越来越多, 这些nosql数据库中的数据就需要java层面的处理。 Stream和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是和计算相关的。 前者主要是面向内存,后者主要是面向CPU。 Stream到底是干什么的? 用于操作数据源(集合,数组)所生成的元素序列。集合讲的是数据,Stream讲得是计算。 注意: (1)Stream不会自己存储元素 (2)Stream不会改变源对象,相反它会返回一个持有结果的新的Stream (3)Stream操作是延迟执行的,这意味着他会等到需要结果的时候再去执行 Stream操作的三大步骤: (1)创建Stream:一个数据源(如集合、数组)获取一个流 (2)中间操作:一个中间操作链,对数据源的数据进行处理 (3)终止操作:一旦执行终止操作就执行中间操作链,并产生结果,之后不会再被使用。
创建Stream的几大方式:
package com.sf.javalearning0929;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/*
Stream 是java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,
可以执行非常复杂的查找,过滤,映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。
简而言之,Stream API提供了一种高效且易于使用的处理数据的方式。
为什么要使用Stream API?
实际开发中,有许多数据源来自mysql oracle等关系型数据库,随着现在应用场景的需要,MongDB REDIS这样nosql数据库也用得越来越多,
这些nosql数据库中的数据就需要java层面的处理。
Stream和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是和计算相关的。
前者主要是面向内存,后者主要是面向CPU。
Stream到底是干什么的?
用于操作数据源(集合,数组)所生成的元素序列。集合讲的是数据,Stream讲得是计算。
注意:
(1)Stream不会自己存储元素
(2)Stream不会改变源对象,相反它会返回一个持有结果的新的Stream
(3)Stream操作是延迟执行的,这意味着他会等到需要结果的时候再去执行
Stream操作的三大步骤:
(1)创建Stream:一个数据源(如集合、数组)获取一个流
(2)中间操作:一个中间操作链,对数据源的数据进行处理
(3)终止操作:一旦执行终止操作就执行中间操作链,并产生结果,之后不会再被使用。
*/
public class StreamAptLearning01 {
//创建Stream方式一:通过集合
@Test
public void test01(){
List<Employee> employees = EmployeeData.getEmployees();
//default Stream<E> stream(): 返回一个顺序流
Stream<Employee> empstream = employees.stream();
//default Stream<E> parallelStream():返回一个并行流
Stream<Employee> empparallelStream = employees.parallelStream();
}
//创建Stream方式二:通过数组
//Java8中的Arrays的静态方法stream()可以获取数组流
//static <T> Stream<T> straem(T[] array)
@Test
public void test02(){
int[] arr = new int[]{2,3,4};
//调用Arrays类的static <T> Stream<T> straem(T[] array):返回一个流
IntStream stream = Arrays.stream(arr);
Employee e1 = new Employee("we",23,1,2222);
Employee e2 = new Employee("are",24,2,2222);
Employee[] arr1 = new Employee[]{e1,e2};
Stream<Employee> stream1 = Arrays.stream(arr1);
}
//创建Stream方式三:通过stream的of()方法
@Test
public void test03(){
Stream<Integer> integerStream = Stream.of(1, 2, 3);
}
//创建Stream方式四:创建无限流
@Test
public void test04(){
//迭代
//public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f)
Stream.iterate(0,t -> t + 2).limit(10).forEach(System.out :: println);
//生成
//public static<T> Stream<T> generate(Supplier<T> s)
Stream.generate(Math :: random).limit(10).forEach(System.out :: println);
}
}
class EmployeeData{
public static List<Employee> getEmployees(){
List<Employee> list = new ArrayList<>();
list.add(new Employee("张3",24,01,3000));
list.add(new Employee("张4",34,02,4000));
list.add(new Employee("张5",54,03,5000));
list.add(new Employee("张6",64,04,6000));
list.add(new Employee("张7",14,05,9000));
return list;
}
}
Stream的中间操作:
Stream的多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理。
在终止操作时一次性全部处理,称为惰性求值。
Stream的中间操作:
(1)筛选与切片
(2)映射
(3)排序
package com.sf.javalearning0929;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/*
Stream的多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理。
在终止操作时一次性全部处理,称为惰性求值。
Stream的中间操作:
(1)筛选与切片
(2)映射
(3)排序
*/
public class StreamApiLearning02 {
@Test
//筛选与切片
public void test01(){
List<Employee> list = EmployeeData.getEmployees();
//filter(Predicate p) 接收lambda,从流中排除某些元素
list.stream().filter(employee -> employee.getAge() > 34).forEach(System.out :: println);
System.out.println("***************************");
//limit(n)-截断流,使其元素数量不超过指定数量
list.stream().limit(2).forEach(System.out :: println);
System.out.println("********************************");
//skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个则返回一个空流
list.stream().skip(1).forEach(System.out :: println);
System.out.println("********************************");
//distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
list.stream().distinct().forEach(System.out :: println);
}
@Test
//映射
//map(Function f) --接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每一个元素上面并将其映射为一个新的元素
public void test02(){
List<String> list = Arrays.asList("aa", "bb", "cc");
list.stream().map(s -> s.toUpperCase()).forEach(System.out :: println);
List<Employee> empList = EmployeeData.getEmployees();
empList.stream().map(s -> s.getName()).filter(a -> a.length() > 1).distinct().forEach(System.out :: println);
}
//flatMap(Function f) 和map(Function f)的区别
@Test
//排序
//sorted() 产生一个新流,其中按自然顺序排序
//sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
public void test03(){
//sorted() 产生一个新流,其中按自然顺序排序
List<Integer> list = Arrays.asList(1,2,3,4);
list.stream().sorted().forEach(System.out :: println);
List<Employee> employeeslist = EmployeeData.getEmployees();
//这样会报错,因为Employee类没有实现Comparable接口
// employeeslist.stream().sorted().forEach(System.out :: println);
//sorted(Comparator com) 产生一个新流,其中按比较器顺序排序
employeeslist
.stream()
.sorted((e1,e2) -> Integer.compare(e1.getAge(),e2.getAge()))
.distinct()
.forEach(System.out :: println);
}
}
终止操作:
(1):匹配和查找
(2):归约
(3):收集
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
Stream的终止操作:
(1):匹配和查找
(2):归约
(3):收集
*/
public class StreamLearning03 {
//匹配和查找
@Test
public void test01(){
List<Employee> employeeslist = EmployeeData.getEmployees();
//allMatch(Predicate p) 检查是否匹配所有元素
System.out.println(employeeslist.stream().allMatch(e -> e.getAge() > 18));
//anyMatch(Predicate p) 检查是否至少匹配一个元素
System.out.println(employeeslist.stream().anyMatch(e -> e.getSalary() > 1000));
//nonMatch(Predicate p) 检查是否没有匹配的元素
System.out.println(employeeslist.stream().noneMatch(e -> e.getName().startsWith("3")));
//findFirst() 返回第一个元素
System.out.println(employeeslist.stream().findFirst());
//findAny 返回任意一元素
System.out.println(employeeslist.stream().findAny());
//count 返回流中元素的总个数
System.out.println(employeeslist.stream().count());
//max(Comparator c)返回流中最大元素
System.out.println(employeeslist.stream().map(e -> e.getSalary()).max((e1,e2) -> Integer.compare(e1,e2)));
//min(Comparator c)返回流中最小元素
System.out.println(employeeslist.stream().min((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary())));
//forEach(Consumer c)内部迭代
employeeslist.stream().forEach(System.out::println);
}
//归约
@Test
public void test02(){
//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, (a, b) -> Integer.sum(a, b)));
//计算所有员工工资的总和
List<Employee> employeeslist = EmployeeData.getEmployees();
System.out.println(employeeslist.stream().map(e -> e.getSalary()).reduce((e1, e2) -> (Integer.sum(e1,e2))));
//可以拆分为以下几步
Stream<Integer> salarySream = employeeslist.stream().map(e -> e.getSalary());
Optional<Integer> salaries = salarySream.reduce((e1, e2) -> Integer.sum(e1, e2));
System.out.println(salaries);
List<Employee> collect = employeeslist.stream().filter(e -> e.getSalary() > 2000).collect(Collectors.toList());
collect.forEach(System.out::println);
}
//收集
@Test
public void test03(){
}
}