Stream API – > java.util.stream
Stream是java8中处理集合的关键抽象概念
可以执行非常复杂的查找、过滤和映射数据等操作
类似于使用SQL执行的数据库查询
Stream API提供了一种高效且易于使用的数据处理方式
Collection是一种静态的内存数据,主要面向内存,存储在内存中
Stream与计算有关,主要面向CPU,通过CPU实现计算
注意:
- Stream 自己不会存储元素
- Stream 不会改变源对象。会返回一个持有结果的新Stream
- Stream 操作时延迟执行的,需要结果的时候才执行
// default Stream<E> stream();
List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> stream = employees.stream();
// default Stream<E> parallelStream()
List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> parallelStream = employees.parallelStream();
// Arrays static <T> Stream<T> stream(T[] array)
Employee[] empArr = employees.toArray(new Employee[employees.size()]);
Stream<Employee> stream1 = Arrays.stream(empArr);
int[] iArr = {1,2,3};
IntStream intStream = Arrays.stream(iArr);
// static<T> Stream<T> of(T... values);
Stream<String> stringStream = Stream.of("1", "2", "3", "4");
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
public static<T> Stream<T> generate(Supplier<T> s)
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
Stream.generate(Math::random).limit(10).forEach(System.out::println);
多个中间操作可以链接起形成一条链,除非链上触发终止操作,否则中间操作不会执行任何处理,只有在终止操作时一次性全部处理,称为惰性求值
方法 | 描述 |
---|---|
filter(Predicate p) | 接收Lambda,从流中排出某些元素 |
distinct() | 筛选,通过流所生成元素的hashCode() 和equals() 去除重复元素 |
limit(long maxSize) | 截断流,使元素不超过给定数量 |
skip(long n) | 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(long maxSize) 互补 |
// filter(Predicate p) 接收Lambda,从流中排出某些元素
List<Employee> list = EmployeeData.getEmployees();
Stream<Employee> stream = list.stream();
// 查询员工薪资大于90000
stream.filter(e -> e.getSalary() > 90000).forEach(System.out::println);
System.out.println("******************************************************");
stream = list.stream();
// limit(long maxSize) 截断流,使元素不超过给定数量
stream.limit(3).forEach(System.out::println);
System.out.println("******************************************************");
// skip(long n) 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与 limit(long maxSize) 互补
list.stream().skip(5).forEach(System.out::println);
System.out.println("******************************************************");
// distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
list.stream().distinct().forEach(System.out::println);
方法 | 描述 |
---|---|
map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素 |
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的DoubleStream |
mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的IntStream |
mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的LongStream |
flatMap(Function f) | 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 |
// 中间操作:映射
@Test
public void test3() {
// map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素
List<String> list = Arrays.asList(new String[]{"tom", "jerry"});
list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
List<Employee> employeeList = EmployeeData.getEmployees();
employeeList.stream().map(Employee::getName).filter(name -> name.length() > 3).forEach(System.out::println);
System.out.println("########################################S");
// flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
list.stream().map(StreamAPITest::stringToStream).forEach(s -> {
s.forEach(System.out::println);
});
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
list.stream().flatMap(StreamAPITest::stringToStream).forEach(System.out::println);
}
public static Stream<Character> stringToStream(String str) {
List<Character> list = new ArrayList<>();
for (char c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
方法 | 描述 |
---|---|
sorted() | 自然排序 |
sorted(Comparator com) | 按比较强顺序排序 |
// sorted() 自然排序
List<Integer> intList = Arrays.asList(2, 6, 2, 1, 7, 12, 45, 67);
intList.stream().sorted().forEach(System.out::println);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// sorted(Comparator com) 按比较强顺序排序
List<Employee> list = EmployeeData.getEmployees();
list.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())).forEach(System.out::println);
会使流产生结果,其中的结果可以是任何不是流的值,如:List,Integer,void。流进行终止操作后,不能再次使用。
方法 | 描述 |
---|---|
allMatch(Predicate p) | 检查是否匹配到所有元素 |
anyMatch(Predicate p) | 检查是否匹配到至少一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配到所有元素 |
findFirst() | 返回第一个元素 |
findAny() | 返回当前流中的任意元素 |
count() | 返回流中元素总数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 内部迭代 ,使用Collection接口需要yoghurt去做的迭代叫外部迭代,StreamAPI使用内部迭代。也可以用Collection.forEach(Consumer c)做迭代 |
// 匹配与查找
@Test
public void test1() {
// | allMatch(Predicate p) | 检查是否匹配到所有元素 |
List<Employee> list = EmployeeData.getEmployees();
boolean b = list.stream().allMatch(e -> e.getAge() >= 30);
System.out.println(b);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// | anyMatch(Predicate p) | 检查是否匹配到至少一个元素 |
boolean b1 = list.stream().anyMatch(e -> e.getSalary() > 50000);
System.out.println(b1);
System.out.println("####################################################");
// | noneMatch(Predicate p) | 检查是否没有匹配到所有元素 |
boolean b2 = list.stream().noneMatch(e -> e.getName().contains("马"));
System.out.println(b2);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@S");
// | findFirst() | 返回第一个元素 |
Optional<Employee> firstEmployee = list.stream().sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())).findFirst();
System.out.println(firstEmployee);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// | findAny() | 返回当前流中的任意元素 |
Optional<Employee> anyEmployee = list.parallelStream().findAny();
System.out.println(anyEmployee);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// | count() | 返回流中元素总数 |
long count = list.stream().count();
System.out.println(count);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// | max(Comparator c) | 返回流中最大值 | 注意,比较方法写反了,取得最小值
// Optional<Employee> max = list.stream().max((e1, e2) -> Double.compare(e2.getSalary(), e1.getSalary()));
Optional<Employee> max = list.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println("max:" + max);
Optional<Double> maxSalary = list.stream().map(Employee::getSalary).max(Double::compare);
System.out.println("maxSalary:" + maxSalary);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// | min(Comparator c) | 返回流中最小值 |
Optional<Employee> min = list.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(min);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
// | forEach(Consumer c) | 内部迭代 |
list.stream().forEach(System.out::println);
}
方法 | 描述 |
---|---|
reduce(T iden, BunaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回T |
reduce(BinaryOperator b) | 将流中元素反复结合,得到一个值。返回Optional<T> |
**备注:**map和reduce的连接通常称为map-reduce模式,因Google用它来进行网络搜索而出名
// 归约
@Test
public void test3() {
// | reduce(T iden, BunaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回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);
// | reduce(BinaryOperator b) | 将流中元素反复结合,得到一个值。返回Optional\<T> |
List<Employee> employeeList = EmployeeData.getEmployees();
Optional<Double> reduce1 = employeeList.stream().map(Employee::getSalary).reduce(Double::sum);
System.out.println(reduce1);
}
方法 | 描述 |
---|---|
collect(Collector c) | 将流转换为其他形式。接收一个Collector接口的实现 |
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)
Collectors实现类提供了很多的静态方法,可以方便地创建常见收集器实例,方法见下表:
方法 | 返回类型 | 作用 | 示例 |
---|---|---|---|
toList | List<T> | 把流中元素收集到List | list.stream().collect(Collectors.toList()) |
toSet | Set<T> | 把流中元素收集到Set | list.stream().collect(Collectors.toSet()) |
toCollection | Collection<T> | 把流中元素收集到创建的集合 | list.stream().collect(Collectors.toCollection(ArrayList::new)) |
counting | Long | 计算流中元素个数 | list.stream().collect(Collectors.counting()) |
summingInt | Integer | 对流中元素整数属性进行求和 | list.stream().collect(Collectors.summingInt(Employee::getSalary)) |
averagingInt | Integer | 对流中Integer属性求平均值 | list.stream().collect(Collectors.averagingInt(Employee::getAge)) |
summarizingInt | IntSummaryStatics | 收集流中Integer属性的统计值。如平均值 | list.stream().collect(Collectors.summarizingInt(Employee::getAge)) |
joining | String | 连接流中每个字符串 | list.stream().collect(Collectors.joining()) |
maxBy | Optional<T> | 根据比较器获取最大值 | list.stream().collect(Collectors.maxBy(Employee::getSalary)) |
minBy | Optional<T> | 根据比较器获取最小值 | list.stream().collect(Collectors.minBy(Employee::getSalary)) |
reducing | 归约产生的类型 | 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值 | list.stream().collect(Collectors.reducing(0, Employee::getSalary, Integer::sum)) |
collectIngAndThen | 转换函数返回的类型 | 包裹另一个收集器,对其结果转换函数 | list.stream().collect(Collectors.collectIngAndThen(Collectors.toList(), List::size)) |
groupingBy | Map<k, List<T>> | 根据某属性值对流分组,属性为K,结果为V | list.stream().collect(Collectors.groupingBy(Employee::getStatus) |
partitioningBy | Map<Boolean, List<T>> | 根据true或false进行分区 | list.stream().collect(Collectors.partitioningBy(Employee::getManage) |
// 收集
@Test
public void test4() {
// | collect(Collector c) | 将流转换为其他形式。接收一个Collector接口的实现 |
List<Employee> list = EmployeeData.getEmployees();
List<Employee> collect = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toList());
System.out.println(collect);
System.out.println();
// | toSet | Set\<T> | 把流中元素收集到Set| list.stream().collect(Collectors.toSet()) |
Set<Employee> collect1 = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toSet());
System.out.println(collect1);
System.out.println();
// | toCollection | Collection\<T> | 把流中元素收集到创建的集合| list.stream().collect(Collectors.toCollection(ArrayList::new)) |
ArrayDeque<Employee> collect2 = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toCollection(ArrayDeque::new));
System.out.println(collect2);
System.out.println();
// | counting | Long | 计算流中元素个数 | list.stream().collect(Collectors.counting()) |
Long collect3 = list.stream().collect(Collectors.counting());
System.out.println(collect3);
// | summingInt | Integer | 对流中元素整数属性进行求和|list.stream().collect(Collectors.summingInt(Employee::getSalary)) |
Integer collect4 = list.stream().collect(Collectors.summingInt(Employee::getAge));
System.out.println(collect4);
IntSummaryStatistics collect5 = list.stream().collect(Collectors.summarizingInt(Employee::getAge));
System.out.println("collect5:" + collect5);
}