Stream概述
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
什么是Stream?
流(Stream) 到底是什么呢?
可以这么理解流:流就是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算! ”
注意:
① Stream 自己不会存储元素。
② Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③ Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream操作步骤
1.创建 Stream
一个数据源(如: 集合、数组), 获取一个流。
2.中间操作
一个中间操作链,对数据源的数据进行处理。
3.终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果 。
如何创建Stream流?
1. 通过Collection系列集合提供的stream()方法或者parallelStream()方法来创建Stream。
在Java8中,Collection 接口被扩展,提供了两个获取流的默认方法,如下所示。
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
其中,stream()方法返回一个顺序流,parallelStream()方法返回一个并行流。
我们可以使用如下代码方式来创建顺序流和并行流。
List<String> list = new ArrayList<>();
list.stream();
list.parallelStream();
2. 通过Arrays中的静态方法stream()获取数组流。
Java8 中的 Arrays类的静态方法 stream() 可以获取数组流 ,如下所示。
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
上述代码的的作用为:传入一个泛型数组,返回这个泛型的Stream流。
除此之外,在Arrays类中还提供了stream()方法的如下重载形式。
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
}
public static IntStream stream(int[] array) {
return stream(array, 0, array.length);
}
public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false);
}
public static LongStream stream(long[] array) {
return stream(array, 0, array.length);
}
public static LongStream stream(long[] array, int startInclusive, int endExclusive) {
return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false);
}
public static DoubleStream stream(double[] array) {
return stream(array, 0, array.length);
}
public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
}
基本上能够满足将基本类型的数组转化为Stream流的操作。
我们可以通过下面的代码示例来使用Arrays类的stream()方法来创建Stream流。
Integer[] nums = new Integer[]{1,2,3,4,5,6,7,8,9};
Stream<Integer> numStream = Arrays.stream(nums);
3. 通过Stream类的静态方法of()获取数组流。
可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。
如下:
public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
@SafeVarargs
@SuppressWarnings("varargs")
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
可以看到,在Stream类中,提供了两个of()方法,一个只需要传入一个泛型参数,一个需要传入一个可变泛型参数。
我们可以使用下面的代码示例来使用of方法创建一个Stream流。
Stream<String> strStream = Stream.of("a", "b", "c");
4. 创建无限流
可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。
先来看看Stream类中iterate()方法和generate()方法的源码,如下所示。
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
Objects.requireNonNull(f);
final Iterator<T> iterator = new Iterator<T>() {
@SuppressWarnings("unchecked")
T t = (T) Streams.NONE;
@Override
public boolean hasNext() {
return true;
}
@Override
public T next() {
return t = (t == Streams.NONE) ? seed : f.apply(t);
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iterator,
Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
}
public static<T> Stream<T> generate(Supplier<T> s) {
Objects.requireNonNull(s);
return StreamSupport.stream(
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}
通过源码可以看出,iterate()方法主要是使用“迭代”的方式生成无限流,而generate()方法主要是使用“生成”的方式生成无限流。我们可以使用下面的代码示例来使用这两个方法生成Stream流。
- 迭代
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2);
intStream.forEach(System.out::println);
运行上述代码,会在终端一直输出偶数,这种操作会一直持续下去。如果我们只需要输出10个偶数,该如何操作呢?其实也很简单,使用Stream对象的limit方法进行限制就可以了,如下所示。
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2);
intStream.limit(10).forEach(System.out::println);
- 生成
Stream.generate(() -> Math.random()).forEach(System.out::println);
上述代码同样会一直输出随机数,如果我们只需要输出5个随机数,则只需要使用limit()方法进行限制即可。
Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);
5. 创建空流
在Stream类中提供了一个empty()方法,如下所示。
public static<T> Stream<T> empty() {
return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);
}
我们可以使用Stream类的empty()方法来创建一个空Stream流,如下所示。
Stream<String> empty = Stream.empty();
Stream的中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值” 。 Stream的中间操作是不会有任何结果数据输出的。
Stream的中间操作在整体上可以分为:筛选与切片、映射、排序。接下来,我们就分别对这些中间操作进行简要的说明。
筛选与切片
方法 | 描述 |
---|---|
filter(Predicate p) | 接收Lambda表达式,从流中排除某些元素 |
distinct() | 筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素 |
limit(long maxSize) | 截断流,使其元素不超过给定数量 |
skip(long n) | 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补 |
列举几个简单的示例,以便加深理解。
先构造了一个对象数组,如下所示。
protected List<Employee> list = Arrays.asList(
new Employee("张三", 18, 9999.99),
new Employee("李四", 38, 5555.55),
new Employee("王五", 60, 6666.66),
new Employee("赵六", 8, 7777.77),
new Employee("田七", 58, 3333.33)
);
其中,Employee类的定义如下所示。
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
private static final long serialVersionUID = -9079722457749166858L;
private String name;
private Integer age;
private Double salary;
}
1.filter()方法
filter()方法主要是用于接收Lambda表达式,从流中排除某些元素,其在Stream接口中的源码如下所示。
Stream<T> filter(Predicate<? super T> predicate);
可以看到,在filter()方法中,需要传递Predicate接口的对象,Predicate接口又是个什么呢?点进去看下源码。
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
可以看到,Predicate是一个函数式接口,其中接口中定义的主要方法为test()方法,test()方法会接收一个泛型对象t,返回一个boolean类型的数据。
所以:filter()方法是根据Predicate接口的test()方法的返回结果来过滤数据的,如果test()方法的返回结果为true,符合规则;如果test()方法的返回结果为false,则不符合规则。
这里,我们可以使用下面的示例来简单的说明filter()方法的使用方式。
//内部迭代:在此过程中没有进行过迭代,由Stream api进行迭代
//中间操作:不会执行任何操作
Stream<Person> stream = list.stream().filter((e) -> {
System.out.println("Stream API 中间操作");
return e.getAge() > 30;
});
上述代码在执行终止语句之后,会一边迭代,一边打印,而我们并没有去迭代上面集合,其实这是内部迭代,由Stream API 完成。
下面我们来看看外部迭代,也就是我们人为得迭代。
//外部迭代
Iterator<Person> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
2.limit()方法
主要作用为:截断流,使其元素不超过给定数量。
先来看limit方法的定义,如下所示。
Stream<T> limit(long maxSize);
limit()方法在Stream接口中的定义比较简单,只需要传入一个long类型的数字即可。
我们可以按照如下所示的代码来使用limit()方法。
//过滤之后取2个值
list.stream().filter((e) -> e.getAge() >30 ).limit(2).forEach(System.out :: println);
在这里,我们可以配合其他得中间操作,并截断流,使我们可以取得相应个数得元素。而且在上面计算中,只要发现有2条符合条件得元素,则不会继续往下迭代数据,可以提高效率。
3.skip()方法
跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补。
源码定义如下所示。
Stream<T> skip(long n);
源码定义比较简单,同样只需要传入一个long类型的数字即可。其含义是跳过n个元素。
简单示例如下所示。
//跳过前2个值
list.stream().skip(2).forEach(System.out :: println);
4.distinct()方法
筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素。
源码定义如下所示。
Stream<T> distinct();
旨在对流中的元素进行去重。
我们可以如下面的方式来使用disinct()方法。
list.stream().distinct().forEach(System.out :: println);
这里有一个需要注意的地方:distinct 需要实体中重写hashCode()和 equals()方法才可以使用。
映射
关于映射相关的方法如下表所示。
方法 | 描述 |
---|---|
map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。 |
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。 |
mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream。 |
mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream |
flatMap(Function f) | 接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流 |
1.map()方法
接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。
先来看Java8中Stream接口对于map()方法的声明,如下所示。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
我们可以按照如下方式使用map()方法。
//将流中每一个元素都映射到map的函数中,每个元素执行这个函数,再返回
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
list.stream().map((e) -> e.toUpperCase()).forEach(System.out::printf);
//获取Person中的每一个人得名字name,再返回一个集合
List<String> names = this.list.stream().map(Person :: getName).collect(Collectors.toList());
2.flatMap()
接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流。
先来看Java8中Stream接口对于flatMap()方法的声明,如下所示。
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
测试flatMap()方法的所有代码:
/**
* flatMap —— 接收一个函数作为参数,将流中的每个值都换成一个流,然后把所有流连接成一个流
*/
@Test
public void testFlatMap () {
StreamAPI_Test s = new StreamAPI_Test();
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
list.stream().flatMap((e) -> s.filterCharacter(e)).forEach(System.out::println);
//如果使用map则需要这样写
list.stream().map((e) -> s.filterCharacter(e)).forEach((e) -> {
e.forEach(System.out::println);
});
//打印aaabbbcccddd
}
/**
* 将一个字符串转换为流
*/
public Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character ch : str.toCharArray()) {
list.add(ch);
}
return list.stream();
}
其实map方法就相当于Collaction的add方法,如果add的是个集合得话就会变成二维数组,而flatMap 的话就相当于Collaction的addAll方法,参数如果是集合得话,只是将2个集合合并,而不是变成二维数组。
排序
关于排序相关的方法如下表所示。
方法 | 描述 |
---|---|
sorted() | 产生一个新流,其中按自然顺序排序 |
sorted(Comparator comp) | 产生一个新流,其中按比较器顺序排序 |
从上述表格可以看出:sorted有两种方法,一种是不传任何参数,叫自然排序,还有一种需要传Comparator 接口参数,叫做定制排序。
先来看Java8中Stream接口对于sorted()方法的声明,如下所示。
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
我们也可以按照如下方式来使用Stream的sorted()方法。
// 自然排序
List<Employee> persons = list.stream().sorted().collect(Collectors.toList());
//定制排序
List<Employee> persons1 = list.stream().sorted((e1, e2) -> {
if (e1.getAge() == e2.getAge()) {
return 0;
} else if (e1.getAge() > e2.getAge()) {
return 1;
} else {
return -1;
}
}).collect(Collectors.toList());
Stream的终止操作
终止操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如: List、 Integer、Double、String等等,甚至是 void 。
在Java8中,Stream的终止操作可以分为:查找与匹配、规约和收集。
查找与匹配
Stream API中有关查找与匹配的方法如下表所示。
方法 | 描述 |
---|---|
allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配所有元素 |
findFirst() | 返回第一个元素 |
findAny() | 返回当前流中的任意元素 |
count() | 返回流中元素总数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代) |
同样的,这里,先建立一个Employee类,Employee类的定义如下所示。
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
private static final long serialVersionUID = -9079722457749166858L;
private String name;
private Integer age;
private Double salary;
private Stauts stauts;
public enum Stauts{
WORKING,
SLEEPING,
VOCATION
}
}
接下来,测试类中定义一个用于测试的集合employees,如下所示。
protected List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Stauts.SLEEPING),
new Employee("李四", 38, 5555.55, Employee.Stauts.WORKING),
new Employee("王五", 60, 6666.66, Employee.Stauts.WORKING),
new Employee("赵六", 8, 7777.77, Employee.Stauts.SLEEPING),
new Employee("田七", 58, 3333.33, Employee.Stauts.VOCATION)
);
1.allMatch()
allMatch()方法表示检查是否匹配所有元素。其在Stream接口中的定义如下所示。
boolean allMatch(Predicate<? super T> predicate);
可以通过类似如下示例来使用allMatch()方法。
boolean match = employees.stream().allMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);
注意:使用allMatch()方法时,只有所有的元素都匹配条件时,allMatch()方法才会返回true。
2.anyMatch()方法
anyMatch方法表示检查是否至少匹配一个元素。其在Stream接口中的定义如下所示。
boolean anyMatch(Predicate<? super T> predicate);
通过类似如下示例来使用anyMatch()方法。
boolean match = employees.stream().anyMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);
注意:使用anyMatch()方法时,只要有任意一个元素符合条件,anyMatch()方法就会返回true。
3.noneMatch()方法
noneMatch()方法表示检查是否没有匹配所有元素。其在Stream接口中的定义如下所示。
boolean noneMatch(Predicate<? super T> predicate);
通过类似如下示例来使用noneMatch()方法。
boolean match = employees.stream().noneMatch((e) -> Employee.Stauts.SLEEPING.equals(e.getStauts()));
System.out.println(match);
注意:使用noneMatch()方法时,只有所有的元素都不符合条件时,noneMatch()方法才会返回true。
4.findFirst()方法
findFirst()方法表示返回第一个元素。其在Stream接口中的定义如下所示。
Optional<T> findFirst();
通过类似如下示例来使用findFirst()方法。
Optional<Employee> op = employees.stream().sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())).findFirst();
System.out.println(op.get());
5.findAny()方法
findAny()方法表示返回当前流中的任意元素。其在Stream接口中的定义如下所示。
findAny()方法的行为是不确定的,它可以自由选择流中的任何元素。
findAny()方法有助于在并行操作中获得最大的性能,但它不能保证每次调用都得到相同的结果。
Optional<T> findAny();
通过类似如下示例来使用findAny()方法。
Optional<Employee> op = employees.stream().filter((e) -> Employee.Stauts.WORKING.equals(e.getStauts())).findFirst();
System.out.println(op.get());
注意:
假设我们有一个整数流。
Stream.of(10, 20, 30).findAny().ifPresent(s -> System.out.println(s));
此执行在一般情况下,并不会随机输出,而是按顺序输出,因为该流是有顺序的串行流,按照最优执行会按照顺序。
如果我们想要看到随机选择,需要改成并行流。
Stream.of(10, 20, 30).parallel().findAny().ifPresent(s -> System.out.println(s));
再次调用findAny方法时,可以自由选择流中的任何元素,这意味着findAny可以给出10、20或30的输出。
注: findAny不是为了随机而随机,而是为了进行最快速的选择,所以最好不要用在随机选择的场景。
6.count()方法
count()方法表示返回流中元素总数。其在Stream接口中的定义如下所示。
long count();
通过类似如下示例来使用count()方法。
long count = employees.stream().count();
System.out.println(count);
7.max()方法
max()方法表示返回流中最大值。其在Stream接口中的定义如下所示。
Optional<T> max(Comparator<? super T> comparator);
通过类似如下示例来使用max()方法。
Optional<Employee> op = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(op.get());
8.min()方法
min()方法表示返回流中最小值。其在Stream接口中的定义如下所示。
Optional<T> min(Comparator<? super T> comparator);
通过类似如下示例来使用min()方法。
Optional<Double> op = employees.stream().map(Employee::getSalary).min(Double::compare);
System.out.println(op.get());
9.forEach()方法
forEach()方法表示内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代)。其在Stream接口内部的定义如下所示。
void forEach(Consumer<? super T> action);
通过类似如下示例来使用forEach()方法。
employees.stream().forEach(System.out::println);
规约
Stream API中有关规约的方法如下表所示。
方法 | 描述 |
---|---|
reduce(T iden, BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。 返回 T |
reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。 返回 Optional |
1.reduce()方法
在Stream接口中的定义如下所示。
T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
通过类似如下示例来使用reduce方法。
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);
System.out.println("----------------------------------------");
Optional<Double> op = employees.stream().map(Employee::getSalary).reduce(Double::sum);
System.out.println(op.get());
我们也可以搜索employees列表中“张”出现的次数。
Optional<Integer> sum = employees.stream()
.map(Employee::getName)
.flatMap(TestStreamAPI1::filterCharacter)
.map((ch) -> {
if(ch.equals('张'))
return 1;
else
return 0;
}).reduce(Integer::sum);
System.out.println(sum.get());
注意:上述例子使用了硬编码的方式来累加某个具体值,在实际工作中再优化代码。
收集
方法 | 描述 |
---|---|
collect(Collector c) | 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法 |
collect()方法在Stream接口中的定义如下所示。
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
我们可以通过类似如下示例来使用collect方法。
Optional<Double> max = employees.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(max.get());
Optional<Employee> op = employees.stream()
.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(op.get());
Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(sum);
Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(avg);
Long count = employees.stream().collect(Collectors.counting());
System.out.println(count);
System.out.println("--------------------------------------------");
DoubleSummaryStatistics dss = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(dss.getMax());
如何收集Stream流?
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到 List、 Set、 Map)。 Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例, 具体方法与实例如下表:
方法 | 返回类型 | 作用 |
---|---|---|
toList | List | 把流中元素收集到List |
toSet | Set | 把流中元素收集到Set |
toCollection | Collection | 把流中元素收集到创建的集合 |
counting | Long | 计算流中元素的个数 |
summingInt | Integer | 对流中元素的整数属性求和 |
averagingInt | Double | 计算流中元素Integer属性的平均 值 |
summarizingInt | IntSummaryStatistics | 收集流中Integer属性的统计值。 如:平均值 |
joining | String | 连接流中每个字符串 |
maxBy | Optional | 根据比较器选择最大值 |
minBy | Optional | 根据比较器选择最小值 |
reducing | 归约产生的类型 | 从一个作为累加器的初始值开始,利用BinaryOperator与 流中元素逐个结合,从而归约成单个值 |
collectingAndThen | 转换函数返回的类型 | 包裹另一个收集器,对其结 果转换函数 |
groupingBy | Map | 根据某属性值对流分组,属 性为K,结果为V |
partitioningBy | Map | 根据true或false进行分区 |
每个方法对应的使用示例如下表所示。
方法 | 使用示例 |
---|---|
toList | List employees= list.stream().collect(Collectors.toList()); |
toSet | Set employees= list.stream().collect(Collectors.toSet()); |
toCollection | Collection employees=list.stream().collect(Collectors.toCollection(ArrayList::new)); |
counting | long count = list.stream().collect(Collectors.counting()); |
summingInt | int total=list.stream().collect(Collectors.summingInt(Employee::getSalary)); |
averagingInt | double avg= list.stream().collect(Collectors.averagingInt(Employee::getSalary)) |
summarizingInt | IntSummaryStatistics iss= list.stream().collect(Collectors.summarizingInt(Employee::getSalary)); |
Collectors | String str= list.stream().map(Employee::getName).collect(Collectors.joining()); |
maxBy | Optionalmax= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary))); |
minBy | Optional min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary))); |
reducing | int total=list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum)); |
collectingAndThen | int how= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size)); |
groupingBy | Map map= list.stream() .collect(Collectors.groupingBy(Employee::getStatus)); |
partitioningBy | Mapvd= list.stream().collect(Collectors.partitioningBy(Employee::getManage)); |
public void test4(){
Optional<Double> max = emps.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(max.get());
Optional<Employee> op = emps.stream()
.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(op.get());
Double sum = emps.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(sum);
Double avg = emps.stream()
.collect(Collecors.averagingDouble(Employee::getSalary));
System.out.println(avg);
Long count = emps.stream()
.collect(Collectors.counting());
DoubleSummaryStatistics dss = emps.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(dss.getMax());
标题:Java Stream API的使用
作者:barryzpc
地址:https://myblog.zhengpc.com/articles/2023/09/17/1694954238502.html
说明:转载请注明出处
赞赏:如果对你有帮助,可略微支持一下