JDK8 Stream 操作

函数接口

Predicate

Predicate——用来判断真假的函数接口。这是一个功能接口,其功能方法是 test(Object)。

//example
/**
  * Person{ String name; Integer age; List<Double> weights;}
  */ 
List<Person> data = new ArrayList<Person>() {
    private static final long serialVersionUID = -413144223496548195L;

    {
        add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
        add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
        add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
        add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
    }
};

// 1-Predicate中test方法。
// 打印年龄大于20的Person信息
Predicate<Person> filter = p -> p.getAge() > 20;

for (Person person : data) {
    if (filter.test(person)) {
        System.out.println("当前Person年龄大于20\n>>" + person);
    }
}
// 当前Person年龄大于20
// >>Person{name='小灰2', age=22, weights=[70.0, 72.8, 73.0]}


// 2- Predicate中的and方法,链接多个Predicate对象
Predicate<Person> predicate = p -> p.getAge() > 20;

Predicate<Person> predicate1 = predicate.and(p -> p.getWeights().stream().min(Comparator.comparing(Double::doubleValue)).orElse(0D).compareTo(70D) >= 0);

List<Person> list = data.stream()
        .filter(predicate1).collect(Collectors.toList());

System.out.println(list);

// result
// [Person{name='小灰2', age=22, weights=[70.0, 72.8, 73.0]}]

Consumer

表示接受单个输入参数且不返回结果的操作。与大多数其他功能接口不同,消费者预计将通过side-effects进行操作。

List<Person> data = new ArrayList<Person>() {
    private static final long serialVersionUID = -413144223496548195L;

    {
        add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
        add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
        add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
        add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
    }
};

Consumer<List<?>> print = System.out::print;

print.accept(data);

Function

/**
     * Applies this function to the given argument.
     * 将此函数应用于给定的参数。即自定义参数类型和返回值类型的函数。
     * 
     */
R apply(T t);

/**
     * 
     * 返回一个组装后的函数,这个函数接收的参数为一个Function类型对象(before)。
     * 提供了一种调用链方式的函数,该函数会先执行参数before的apply方法,并将before返回值做为自身apply方法的输入参数。
     * 在执行期间函数调用链中的任一函数发生异常,都会传递给调用链函数的调用方。
     *
     */
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
}

/**
     *
     * 与compose方式提供类似的功能。与其不同的是andThen方法会优先执行自身的apply方法,并将其返回值做为after的输入参数。
     * 在执行期间函数调用链中的任一函数发生异常,都会传递给调用链函数的调用方。
     *
     */
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

/**
     * 
     * 始终返回输入参数的方法
     *
     */
static <T> Function<T, T> identity() {
    return t -> t;
}
compose

组合函数

Function<String, String> before = name -> "before 输入参数[" + name + "]";
Function<String, String> after = name -> "after 输入参数[" + name + "]";

System.out.println("compose:" + after.compose(before).apply("小明"));
扩展
类名 描述
BiFunction 提供了接收2个参数的Function功能
ToDoubleBiFunction 提供了接收个参数并返回double类型的Function功能
ToIntBiFunction 提供了接收2个参数并返回int类型的Function功能
ToLongBiFunction 提供了接收2个参数并返回long类型的Function功能
IntFunction 提供了接收一个int类型参数的Function功能
DoubleFunction 提供了接收一个double类型参数的Function功能
LongFunction 提供了接收一个long类型参数的Function功能
ToDoubleFunction 提供了接收一个参数并返回double类型的Function功能
ToIntFunction 提供了接收一个参数并返回int类型的Function功能
ToLongFunction 提供了接收一个参数并返回long类型的Function功能
DoubleToIntFunction 提供了接收一个double类型参数并返回一个Int类型的Function功能
DoubleToLongFunction 提供了接收一个double类型参数并返回一个long类型的Function功能
IntToDoubleFunction 提供了接收一个int类型参数并返回double类型的Function功能
IntToLongFunction 提供了接收一个long类型参数并返回int类型的Function功能
LongToDoubleFunction 提供了接收一个long类型参数并返回double类型的Function功能
LongToIntFunction 提供了接收一个long类型参数并报返回int类型的Function功能

Supplier

不要求每次调用Supplier时都返回新的或不同的结果。

Steam流只能被消费一次,如果要多次消费,就要通过生产者的方式提供。

List<Person> data = new ArrayList<Person>() {
    private static final long serialVersionUID = -413144223496548195L;

    {
        add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
        add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
        add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
        add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
    }
};

Stream<Person> personStream = data.stream();
personStream.forEach(System.out::println);

System.out.println("================");

Supplier<Stream<Person> > personStreamSupplier = data::stream;

System.out.println("Supplier(1)================");
personStreamSupplier.get().forEach(System.out::println);
System.out.println("Supplier(2)================");
personStreamSupplier.get().forEach(System.out::println);
类名 描述
BooleanSupplier 提供了生产boolean型返回值功能
DoubleSupplier 提供了生产double型返回值功能
IntSupplier 提供了生产int型返回值功能
LongSupplier 提供了生产long型返回值功能

UnaryOperator

表示对单个操作数的操作,该操作产生与其操作数相同类型的结果。对于操作数和结果类型相同的情况,这是 Function 的一种特殊化。

在定义UnaryOperator时,我们需要定义Function.apply(Object),其中Function将是UnaryOperator的实例。

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}
Function<Person, Person> function = s -> s;
data.forEach(s -> System.out.println(function.apply(s)));

UnaryOperator<Person> unaryOperator = s -> s;
data.forEach(s -> System.out.println(unaryOperator.apply(s)));

BinaryOperator

该接口接受两个参数,返回一个值,参数和值的类型均相同。

表示对两个相同类型的操作数的操作,产生与操作数相同类型的结果。这是 BiFunction 的一种特殊化,适用于操作数和结果都是相同类型的情况。

String x = "1";
String y = "2";
String result = StrUtil.isBlank(x) ? y : x;

System.out.println(result);
// result
// 1

BinaryOperator<String> binaryOperator = (a, b) -> {
    if (StrUtil.isBlank(a)) {
        return b;
    }
    return a;
};

System.out.println(binaryOperator.apply(x, y));
// result
// 1
maxBy

返回一个 BinaryOperator,它根据指定的 Comparator 返回两个元素中较大的一个。

// source code
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
    Objects.requireNonNull(comparator);
    return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
List<Person> data = new ArrayList<Person>() {
    private static final long serialVersionUID = -413144223496548195L;

    {
        add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
        add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
        add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
        add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
    }
};


BinaryOperator<Person> binaryOperator =
        BinaryOperator.maxBy(Comparator.comparing(p -> p.getWeights().stream()
                .max(Double::compareTo)
                .orElse(0D)));

Person max = new Person();
for (Person p : data) {
    max = binaryOperator.apply(p, max);
}

System.out.println(max);
// result
// Person{name='小灰4', age=20, weights=[75.0, 72.8, 76.0], pet=null}
minBy

返回一个 BinaryOperator,它根据指定的比较器返回两个元素中较小的一个。

// source code
public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
    Objects.requireNonNull(comparator);
    return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
}
List<Person> data = new ArrayList<Person>() {
    private static final long serialVersionUID = -413144223496548195L;

    {
        add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
        add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
        add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
        add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
    }
};


BinaryOperator<Person> binaryOperator =
        BinaryOperator.minBy(Comparator.comparing(p -> p.getWeights().stream()
                .min(Double::compareTo)
                .orElse(0D)));

Person max = new Person();
for (Person p : data) {
    max = binaryOperator.apply(p, max);
}

System.out.println(max);

// result
// Person{name='null', age=null, weights=[], pet=null}

Stream常用操作

常用类型

collect(Collector collector)

<R, A> R collect(Collector<? super T, A, R> collector);
// 数据 
List<Person> data = new ArrayList<Person>() {
            {
                add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
                add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
                add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
                add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
            }
        };
1、Collectors.toList()

生成ArrayList对象

// 获取Person中的姓名集合
// 1-通常场景
List<String> names = new ArrayList<>();
        for (Person p : data) {
            names.add(p.getName());
        }

System.out.println(names);
// process result
// [小灰1, 小灰2, 小灰3, 小灰4]

// 2-使用Collectors.toList()方式
List<String> names = data.stream().map(Person::getName).collect(Collectors.toList());

System.out.println(names);
// process result
// [小灰1, 小灰2, 小灰3, 小灰4]
2、Collectors.toSet()

生成HashSet对象

// 获取Person中都有哪些年龄的数据
// 1-通常场景
Set<Integer> ages = new HashSet<>();
for (Person p : data) {
    ages.add(p.getAge());
}
System.out.println(ages);

// process result
// [18, 20, 22]

// 2-使用Collectors.toSet()方式
Set<Integer> ages = data.stream().map(Person::getAge).collect(Collectors.toSet());
System.out.println(ages);
// process result
// [18, 20, 22]
3、Collectors.toMap()
public static <T, K, U>
    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                    Function<? super T, ? extends U> valueMapper) 

生成HashMap对象

// 根据名字分组
// 1-通常场景
Map<String,Person> maps = new HashMap<>();
for (Person p : data) {
    maps.put(p.getName(),p);
}

// 2-使用Collectors.toMap()方式
Map<String, Person> maps = data.stream().collect(Collectors.toMap(Person::getName, Function.identity()));
System.out.println(maps);

// process result
// {小灰4=Person{name='小灰4', age=20, weights=[75.0, 72.8, 76.0]}, 
// 小灰3=Person{name='小灰3', age=18, weights=[65.0, 64.8, 63.0]}, 
// 小灰2=Person{name='小灰2', age=22, weights=[70.0, 72.8, 73.0]}, 
// 小灰1=Person{name='小灰1', age=20, weights=[75.0, 74.8, 73.0]}}


// 每个数字分组求和
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 3);
Map<Integer, Integer> map = stream.collect(Collectors.toMap(Function.identity(), Function.identity(), Integer::sum));

System.out.println(map);

// process result
// {1=1, 2=2, 3=6, 4=4}
4、Collectors.toCollection()
//example1

Stream<Integer> stream = Stream.of(1, 2, 3, 4);  
Collection<Integer> collection = stream.collect(Collectors.toCollection(TreeSet::new));

 System.out.println(collection);

// process result
// [1, 2, 3, 4, 3]
5、Collectors.groupingBy()

生成Map对象

//example1

Stream<Integer> stream = Stream.of(1, 2, 3, 4); 
Map<Integer, List<Integer>> map = stream.collect(Collectors.groupingBy(Function.identity()));

System.out.println(map);

// proccess result
// {1=[1], 2=[2], 3=[3], 4=[4]}

与Collectors组合使用

//example2
/**
  * Person{ String name; Integer age;}
  */
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

// 根据年龄分组,并统计数量
Map<Integer, Long> collect = personStream.collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));

System.out.println(collect);
// result
// {18=1, 20=2, 22=1}

// 根据年龄分组,并统计改年龄段的姓名
Map<Integer, List<String>> collect = personStream.collect(Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.toList())));

System.out.println(collect);
// result
// {18=[小灰3], 20=[小灰1, 小灰4], 22=[小灰2]}
6、Collectors.summarizingInt()

summarizingInt 将产生 的映射函数应用于每个输入元素,并返回结果值的汇总统计信息。

与之类似的有 summarizingLong()、summarizingDouble()
//example
/**
  * Person{ String name; Integer age;}
  */
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));


IntSummaryStatistics statisticsAge = personStream.collect(Collectors.summarizingInt(Person::getAge));

long count = statisticsAge.getCount();
System.out.println(count);

double average = statisticsAge.getAverage();
System.out.println(average);

int max = statisticsAge.getMax();
System.out.println(max);

int min = statisticsAge.getMin();
System.out.println(min);

long sum = statisticsAge.getSum();
System.out.println(sum);

// process result

// 数量   4
// 平均值 20.0
// 最大值 22
// 最小值 18
// 求和   80
7、Collectors.summingInt()

summingInt 返回一个收集器,产生应用于输入元素的整数值函数的总和。如果不存在任何元素,则结果为 0。

与之类似的有 summingLong()、summingDouble()
//example
/**
  * Person{ String name; Integer age;}
  */
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

Integer sum = personStream.collect(Collectors.summingInt(Person::getAge));
// 等同于 Integer sum = personStream.mapToInt(Person::getAge).sum();

System.out.println(sum);

// result
// 80
8、Collectors.joining()
Collectors.joining(CharSequence delimiter)

返回一个收集器,它连接输入元素,由指定的分隔符分隔,按照遇到的顺序

//example
/**
  * Person{ String name; Integer age;}
  */
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));


String names = personStream.map(Person::getName).collect(Collectors.joining(","));

System.out.println(names);
// result
// 小灰1,小灰2,小灰3,小灰4
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter, // 分隔符
                                                         CharSequence prefix,      // 前缀
                                                         CharSequence suffix)     // 后缀
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

String names = personStream
        .map(Person::getName)
        .collect(Collectors.joining(",", "[", "}"));

System.out.println(names);

// result 
// [小灰1,小灰2,小灰3,小灰4}
9、Collectors.partitioningBy()
public static <T>
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)
public static <T, D, A>
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
                                                Collector<? super T, A, D> downstream) 

返回一个 Collector,它根据 Predicate 对输入元素进行分区,根据另一个 Collector 对每个分区中的值进行归约,并将它们组织成一个 Map<Boolean, D>,其值是下游归约的结果。不保证返回的 Map 的类型、可变性、可序列化性或线程安全性。

List<Person> data = new ArrayList<Person>() {
    private static final long serialVersionUID = -413144223496548195L;

    {
        add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
        add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
        add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
        add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
    }
};

// 1- 默认返回List
data.stream()
        .collect(Collectors.partitioningBy(p -> p.getAge() > 20))
        .forEach((k, v) -> {
            System.out.println("key:" + k + "\t value:" + v);
        });

// result
//    key:false     value:[Person{name='小灰1', age=20, weights=[75.0, 74.8, 73.0]}, 
//                        Person{name='小灰3', age=18, weights=[65.0, 64.8, 63.0]}, 
//                        Person{name='小灰4', age=20, weights=[75.0, 72.8, 76.0]}]
// key:true         value:[Person{name='小灰2', age=22, weights=[70.0, 72.8, 73.0]}]

// 2- 指定返回的Map中的value值类型
Map<Boolean, Map<String, Person>> maps = data.stream()
                .collect(Collectors.partitioningBy(p -> p.getAge() > 20, Collectors.toMap(Person::getName, Function.identity())));
maps.forEach((k, v) -> {
    System.out.println("key:" + k + "\t value:" + v);
});

// result
// key:false     value:{小灰4=Person{name='小灰4', age=20, weights=[75.0, 72.8, 76.0]}, 
//                        小灰3=Person{name='小灰3', age=18, weights=[65.0, 64.8, 63.0]}, 
//                        小灰1=Person{name='小灰1', age=20, weights=[75.0, 74.8, 73.0]}}
// key:true         value:{小灰2=Person{name='小灰2', age=22, weights=[70.0, 72.8, 73.0]}}

collect(Supplier supplier,BiConsumer accumulator, BiConsumer combiner)

/**
* @param supplier     生产者,最终返回对象
* @param accumulator  累加器,将每一个元素添加到集合中
* @param combiner      合并器,有并行流才会使用
*/
<R> R collect(Supplier<R> supplier,
              BiConsumer<R, ? super T> accumulator,
              BiConsumer<R, R> combiner)
/**
  * Person{ String name; Integer age; List<Double> weights;}
  */  
Stream<Person> personStream = Stream.of(new Person("小灰1", 20, newList(75D, 74.8D, 73D)),
                new Person("小灰2", 22, newList(70D, 72.8D, 73D)),
                new Person("小灰3", 18, newList(65D, 64.8D, 63D)),
                new Person("小灰4", 20, newList(75D, 72.8D, 76D)));


// Map<String, Person> personMap = personStream.collect(Collectors.toMap(Person::getName, Function.identity(), (a, b) -> a));

HashMap<String, Person> personMap = personStream.collect(HashMap::new, (map, p) -> map.put(p.getName(), p), HashMap::putAll);
System.out.println(personMap);

// result 
// {小灰4=Person{name='小灰4', age=20, weights=[75.0, 72.8, 76.0]}, 
//  小灰3=Person{name='小灰3', age=18, weights=[65.0, 64.8, 63.0]}, 
//  小灰2=Person{name='小灰2', age=22, weights=[70.0, 72.8, 73.0]}, 
//  小灰1=Person{name='小灰1', age=20, weights=[75.0, 74.8, 73.0]}}


// 将Person集合中的weights取出放入一个集合中
List<Double> collect = data.stream()
                .map(Person::getWeights)
                .collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
System.out.println(collect);

// result
// [75.0, 74.8, 73.0, 70.0, 72.8, 73.0, 65.0, 64.8, 63.0, 75.0, 72.8, 76.0]

map()

可以将一种类型转换成另一种类型。map操作可以将一个流中的值转换成一个新的流

//example
/**
  * Person{ String name; Integer age;}
  */ 
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

ArrayList<String> maps = personStream.map(Person::getName)
                .collect(Collectors.toCollection(ArrayList::new));

System.out.println(maps);
// result 
// [小灰1, 小灰2, 小灰3, 小灰4]

max和min

获取最大值或者最小值

//example
/**
  * Person{ String name; Integer age;}
  */ 
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

Optional<Integer> optional = personStream.map(Person::getAge)
                .max(Comparator.comparing(Function.identity()));

System.out.println(optional.orElse(0));

//result
// 22

Person person = personStream.max(Comparator.comparingInt(Person::getAge)).orElse(null);

System.out.println(person);
// Person{name='小灰2', age=22}

sorted

排序

//example
/**
  * Person{ String name; Integer age;}
  */ 
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));
personStream.map(Person::getAge)
                .sorted()
                .collect(Collectors.toList())
                .forEach(System.out::println);
//     18
//    20
//    20
//    22

personStream.sorted(Comparator.comparing(Person::getAge))
                .forEach(System.out::println);
// Person{name='小灰3', age=18}
// Person{name='小灰1', age=20}
// Person{name='小灰4', age=20}
// Person{name='小灰2', age=22}

比较器Compartor

filter

保留符合条件的元素,过滤其他的

//example
/**
  * Person{ String name; Integer age;}
  */ 
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

personStream.filter(p -> 20 == p.getAge())
                .forEach(System.out::println);

// result
// Person{name='小灰1', age=20}
// Person{name='小灰4', age=20}

allMatch,anyMatch,noneMatch

allMatch 返回此流的所有元素是否与提供的条件匹配。如果流为空,则返回 true 并且进行条件匹配。

//example
/**
  * Person{ String name; Integer age;}
  */ 
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

// 所有的person的年龄是否都是20以上的
System.out.println(personStream.allMatch(p -> 20 > p.getAge()));

// process result
// false

mapToXX

mapToInt、mapToDouble、mapToLong、mapToObj
//example
/**
  * Person{ String name; Integer age;}
  */ 
Stream<Person> personStream = Stream.of(new Person("小灰1", 20),
                new Person("小灰2", 22),
                new Person("小灰3", 18),
                new Person("小灰4", 20));

String mapToString = personStream
                .mapToLong(Person::getAge)
                .mapToObj(String::valueOf)
                .collect(Collectors.joining(" & ", "[", "]"));

System.out.println(mapToString);

// result 
// [20 & 22 & 18 & 20]

flatMap

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

返回一个流,其中包含将此流的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容的结果。每个映射流在其内容被放入该流后关闭。 (如果映射流为空,则使用空流。)

//example
/**
  * Person{ String name; Integer age; List<Double> weights;}
  */ 
Stream<Person> personStream = Stream.of(new Person("小灰1", 20, newList(75D, 74.8D, 73D)),
                new Person("小灰2", 22, newList(70D, 72.8D, 73D)),
                new Person("小灰3", 18, newList(65D, 64.8D, 63D)),
                new Person("小灰4", 20, newList(75D, 72.8D, 76D)));

long count = personStream.filter(person -> person.getAge() == 20)
    .flatMap(p -> p.getWeights().stream())
    .mapToDouble(Double::valueOf)
    .count();


System.out.println(count);
// result  年龄为20的体重数据条数
// 6

double avg = personStream.filter(person -> person.getAge() == 20)
                .flatMap(p -> p.getWeights().stream())
                .mapToDouble(Double::valueOf)
                .average()
                .orElse(0);

System.out.println(avg);
// result 年龄20的平均体重
// 74.43333333333334

reduce


使用关联累积函数对此流的元素执行归约,并返回描述归约值(如果有)的 Optional.

//example
/**
  * Person{ String name; Integer age; List<Double> weights;}
  */ 
List<Person> data = new ArrayList<Person>() {
    private static final long serialVersionUID = -413144223496548195L;

    {
        add(new Person("小灰1", 20, newList(75D, 74.8D, 73D)));
        add(new Person("小灰2", 22, newList(70D, 72.8D, 73D)));
        add(new Person("小灰3", 18, newList(65D, 64.8D, 63D)));
        add(new Person("小灰4", 20, newList(75D, 72.8D, 76D)));
    }
};

// 求和
double sum = data.stream()
        .flatMap(p -> p.getWeights().stream())
        .mapToDouble(Double::valueOf)
        .sum();

System.out.println(sum);

// result
// 855.2

// reduce 的方式
Double value = data.stream()
        .flatMap(p -> p.getWeights().stream())
        .reduce((x, y) -> BigDecimal.valueOf(x).add(BigDecimal.valueOf(y)).doubleValue())
        .orElse(null);

System.out.println(value);

// result
// 855.2

IntStream

// 遍历1到10
IntStream.range(1, 10)
    .forEach(System.out::println);

// 遍历1到10包含10
IntStream.rangeClosed(1, 10)
    .forEach(System.out::println);


// 生成50以内的三个随机数
IntStream.generate(() -> new Random().nextInt(50))
        .limit(3)
        .forEach(System.out::println);

LongStream

DoubleStream

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
1
粉丝
0
喜欢
0
收藏
1
排名:3296
访问:83
私信
所有博文
社区赞助商