本文分3部分
java8-基础
主要讲述java8的一些基础概念及用法。包括:Optional类,Lambda表达式,Stream接口。
java8-进阶
主要讲述java8的一些进阶用法。包括:Function接口,自定义Stream接口。
java8-实践
主要讲述java8的用法的一些比较特别的实践用法。
点一点链接,支持一波吃饭,http://aliyun.guan2ye.com/
输出的是一个空的 optional
对象
Optional<String> optional = Optional.empty(); System.out.println(optional); ##:Optional.empty 复制代码
如果 person
是 null
,将会立即抛出,而不是访问 person
的属性时获得一个潜在的错误
Person person = new Person("xu","hua"); Optional<Person> optional2 = Optional.of(person); System.out.println(optional2); System.out.println(optional2.get()); System.out.println(optional2.get().firstName); ##:Optional[xuhua] xuhua xu 复制代码
System.out.println(optional.isPresent()); System.out.println(optional2.isPresent()); ##:false true 复制代码
System.out.println(optional.orElse("fallback")); optional.ifPresent(System.out::println); ##:fallback xuhua 复制代码
java8以前的字符串排列,创建一个匿名的比较器对象 Comparator
然后将其传递给 sort
方法
List<String> names= Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return b.compareTo(a); } }); 复制代码
java8
使用 lambda
表达式就不需要匿名对象了
Collections.sort(names,(String a,String b)->{return b.compareTo(a);}); 复制代码
简化一下:对于函数体只有一行代码的,你可以去掉大括号{}以及 return
关键字
Collections.sort(names,(String a,String b)->b.compareTo(a)); 复制代码
Java
编译器可以自动推导出参数类型,所以你可以不用再写一次类型
Collections.sort(names, (a, b) -> b.compareTo(a)); 复制代码
##:[xenia, peter, mike, anna] 复制代码
对于 null
的处理
List<String> names2 = Arrays.asList("peter", null, "anna", "mike", "xenia"); names2.sort(Comparator.nullsLast(String::compareTo)); System.out.println(names2); ##:[anna, mike, peter, xenia, null] 复制代码
每一个 lambda
表达式都对应一个类型,通常是接口类型。
而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的 lambda
表达式都会被匹配到这个抽象方法。
因为默认方法不算抽象方法,所以你也可以给你的函数式接口添加默认方法。
我们可以将 lambda
表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,
你只需要给你的接口添加 @FunctionalInterface
注解,
编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。
函数式接口
@FunctionalInterface public static interface Converter<F, T> { T convert(F from); } /**原始的接口实现*/ Converter<String, Integer> integerConverter1 = new Converter<String, Integer>() { @Override public Integer convert(String from) { return Integer.valueOf(from); } }; /**使用lambda表达式实现接口*/ Converter<String, Integer> integerConverter2 = (from) -> Integer.valueOf(from); Integer converted1 = integerConverter1.convert("123"); Integer converted2 = integerConverter2.convert("123"); System.out.println(converted1); System.out.println(converted2); ##:123 123 /**简写的lambda表达式*/ Converter<String, Integer> integerConverter3 = Integer::valueOf; Integer converted3 = integerConverter3.convert("123"); System.out.println(converted3); ##:123 复制代码
函数式方法
static class Something { String startsWith(String s) { return String.valueOf(s.charAt(0)); } } Something something = new Something(); Converter<String, String> stringConverter = something::startsWith; String converted4 = stringConverter.convert("Java"); System.out.println(converted4); ##:j 复制代码
函数式构造器
Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。
public class Person { public String firstName; public String lastName; public Person() { } public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String toString(){ return firstName+lastName; } } 复制代码
interface PersonFactory<P extends Person> { P create(String firstName, String lastName); } PersonFactory<Person> personFactory = Person::new; Person person = personFactory.create("xu", "hua"); System.out.println(person.toString()); ##:xuhua 复制代码
Lambda作用域 点一点链接,支持一波吃饭,http://aliyun.guan2ye.com/
在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。
你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。
static int outerStaticNum = 10; int outerNum; void testScopes() { /**变量num可以不用声明为final*/ int num = 1; /**可以直接在lambda表达式中访问外层的局部变量*/ Lambda2.Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + outerStaticNum+num); String convert = stringConverter.convert(2); System.out.println(convert); ##:13 /**但是num必须不可被后面的代码修改(即隐性的具有final的语义),否则编译出错*/ //num=3; /**lambda内部对于实例的字段以及静态变量是即可读又可写*/ Lambda2.Converter<Integer, String> stringConverter2 = (from) -> { outerNum = 13; return String.valueOf(from + outerNum); }; System.out.println(stringConverter2.convert(2)); System.out.println("/nBefore:outerNum-->" + outerNum); outerNum = 15; System.out.println("After:outerNum-->" + outerNum); ##:Before:outerNum-->13 After:outerNum-->15 String[] array = new String[1]; Lambda2.Converter<Integer, String> stringConverter3 = (from) -> { array[0] = "Hi here"; return String.valueOf(from); }; stringConverter3.convert(23); System.out.println("/nBefore:array[0]-->" + array[0]); array[0] = "Hi there"; System.out.println("After:array[0]-->" + array[0]); ##:Before:array[0]-->Hi here After:array[0]-->Hi there } 复制代码
点一点链接,支持一波吃饭,http://aliyun.guan2ye.com/
java.util.Stream
表示能应用在一组元素上一次执行的操作序列。
Stream
操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回 Stream
本身,这样你就可以将多个操作依次串起来。
Stream
的创建需要指定一个数据源,比如 java.util.Collection
的子类, List
或者 Set
, Map
不支持。
Stream
的操作可以串行执行或者并行执行。
List<String> stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa2"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); stringCollection.add("bbb3"); stringCollection.add("ccc"); stringCollection.add("bbb2"); stringCollection.add("ddd1"); 复制代码
Filter 过滤.
Filter
通过一个 predicate
接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他 Stream
操作(比如 forEach
)。
forEach
需要一个函数来对过滤后的元素依次执行。
forEac
h是一个最终操作,所以我们不能在 forEach
之后来执行其他 Stream
操作。
stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); 复制代码
Sorted 排序.
Sorted
是一个中间操作,返回的是排序好后的 Stream
。
如果你不指定一个自定义的 Comparator
则会使用默认排序.
stringCollection .stream() .sorted() .forEach(System.out::println); System.out.println(stringCollection);//原数据源不会被改变 复制代码
Map.
中间操作 ma
p会将元素根据指定的 Function
接口来依次将元素转成另外的对象.
stringCollection .stream() .map(String::toUpperCase) .map((s)->s+" space") .sorted((a, b) -> b.compareTo(a)) .forEach(System.out::println); 复制代码
Match
Stream
提供了多种匹配操作,允许检测指定的 Predicate
是否匹配整个 Stream
。
所有的匹配操作都是最终操作,并返回一个boolean类型的值。
boolean anyStartsWithA = stringCollection .stream() .anyMatch((s) -> s.startsWith("a")); System.out.println(anyStartsWithA); // true boolean allStartsWithA = stringCollection .stream() .allMatch((s) -> s.startsWith("a")); System.out.println(allStartsWithA); // false boolean noneStartsWithZ = stringCollection .stream() .noneMatch((s) -> s.startsWith("z")); System.out.println(noneStartsWithZ); // true 复制代码
Count
计数是一个最终操作,返回 Stream
中元素的个数,返回值类型是 long
。
long startsWithB = stringCollection .stream() .filter((s) -> s.startsWith("b")) .count(); System.out.println(startsWithB); // 3 复制代码
Reduce
Reduce
是一个最终操作,允许通过指定的函数来讲 stream
中的多个元素规约为一个元素,规约后的结果是通过 Optional
接口表示的。
Optional<String> reduced = stringCollection .stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); ##:aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2 复制代码
串行stream
List<String> values = new ArrayList<>(MAX); for (int i = 0; i < MAX; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } long t0 = System.nanoTime(); long count = values.stream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("sequential sort took: %d ms", millis)); 复制代码
并行stream
并行 stream
是在运行时将数据划分成了多个块,然后将数据块分配给合适的处理器去处理。
只有当所有块都处理完成了,才会执行之后的代码。
List<String> values = new ArrayList<>(MAX); for (int i = 0; i < MAX; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } long t0 = System.nanoTime(); long count = values.parallelStream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("parallel sort took: %d ms", millis)); 复制代码
时间结果比较:
1000000 sequential sort took: 717 ms 1000000 parallel sort took: 303 ms 复制代码
IntStream
接口是 stream
的一种,继承了 BaseStream
接口。
IntStream.range(0, 10) .forEach(i -> { if (i % 2 == 1) System.out.print(i+" "); }); ##:1 3 5 7 9 OptionalInt reduced1 = IntStream.range(0, 10) .reduce((a, b) -> a + b); System.out.println(reduced1.getAsInt()); int reduced2 = IntStream.range(0, 10) .reduce(7, (a, b) -> a + b); System.out.println(reduced2); ##:45 52 复制代码
System.out.println(IntStream.range(0, 10).sum()); 复制代码
Map<String, Integer> unsortMap = new HashMap<>(); unsortMap.put("z", 10); unsortMap.put("b", 5); unsortMap.put("a", 6); unsortMap.put("c", 20); unsortMap.put("d", 1); unsortMap.put("e", 7); unsortMap.put("y", 8); unsortMap.put("n", 99); unsortMap.put("j", 50); unsortMap.put("m", 2); unsortMap.put("f", 9); 复制代码
使用 stream
类来对 map
的 value
排序
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { Map<K, V> result = new LinkedHashMap<>(); map.entrySet().parallelStream() .sorted((o1, o2) -> (o2.getValue()).compareTo(o1.getValue())) .forEachOrdered(x -> result.put(x.getKey(), x.getValue())); return result; } System.out.println(sortByValue(unsortMap)); ##:{n=99, j=50, c=20, z=10, f=9, y=8, e=7, a=6, b=5, m=2, d=1} 复制代码
List<Object> list = new ArrayList<>(); JSONObject data1 = new JSONObject(); data1.put("type", "支出"); data1.put("money", 500); JSONObject data2 = new JSONObject(); data2.put("type", "收入"); data2.put("money", 1000); JSONObject data3 = new JSONObject(); data3.put("type", "借贷"); data3.put("money", 100); list.add(data1); list.add(data2); list.add(data3); 复制代码
使用 stream
类来处理 list``里面的
json`数据
/** * 按money的值来排列json */ list.stream() .filter(x -> JSONObject.fromObject(x).containsKey("money")) .sorted((b, a) -> Integer.valueOf(JSONObject.fromObject(a).getInt("money")).compareTo(JSONObject.fromObject(b) .getInt("money"))) .forEach(System.out::println); /** * 找到最小的money */ Integer min = list.stream() .filter(x -> JSONObject.fromObject(x).containsKey("money")) .map(x -> JSONObject.fromObject(x).getInt("money")) .sorted() .findFirst() .get(); System.out.println(min); /** * 计算type的数目 */ Map<String, Integer> type_count = new HashMap<>(); list.stream() .filter(x -> JSONObject.fromObject(x).containsKey("type")) .map(x -> JSONObject.fromObject(x).getString("type")) .forEach(x -> { if (type_count.containsKey(x)) type_count.put(x, type_count.get(x) + 1); else type_count.put(x, 1); }); System.out.println(type_count.toString()); ##: {"type":"收入","money":1000} {"type":"支出","money":500} {"type":"借贷","money":100} 100 {借贷=1, 收入=1, 支出=1} 复制代码
点一点链接,支持一波吃饭,http://aliyun.guan2ye.com/
只包含一个抽象方法的接口
Function<T, R>
接受一个输入参数,返回一个结果。
Function接口包含以下方法:
定义两个比较简单的函数: times2
和 squared
Function<Integer, Integer> times2 = e -> e * 2; Function<Integer, Integer> squared = e -> e * e; 复制代码
R apply(T t)
执行函数
//return 8 - > 4 * 2 Integer a = times2.apply(4); System.out.println(a); 复制代码
compose
先执行参数里面的操作,然后执行调用者
//return 32 - > 4 ^ 2 * 2 Integer b = times2.compose(squared).apply(4); System.out.println(b); 复制代码
andThen
先执行调用者操作,再执行参数操作
//return 64 - > (4 * 2) ^ 2 Integer c = times2.andThen(squared).apply(4); System.out.println(c); 复制代码
identity
总是返回传入的参数本身
//return 4 Integer d = identity.apply(4); System.out.println(d); 复制代码
BiFunction<T, U, R>
接受输入两个参数,返回一个结果
R apply(T t, U u)
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y; //return 30 System.out.println(add.apply(10,20)); 复制代码
Supplier<T>
无参数,返回一个结果。
T get()
Supplier<Integer> get= () -> 10; //return 10 Integer a=get.get(); 复制代码
Consumer<T>
代表了接受一个输入参数并且无返回的操作
void accept(T t)
//return void Consumer<Integer> accept=x->{}; 复制代码
BiConsumer<T, U>
代表了一个接受两个输入参数的操作,并且不返回任何结果
void accept(T t, U u)
//return void BiConsumer<Integer,Integer> accept=(x,y)->{}; 复制代码
BinaryOperator<T> extends BiFunction<T,T,T>
一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
定义了两个静态方法: minBy
, maxBy
Predicate<T>
接受一个输入参数,返回一个布尔值结果。
test
Predicate<String> predicate=x->x.startsWith("a"); //return ture System.out.println(predicate.test("abc")); 复制代码
Collector接口
Collector是Stream的可变减少操作接口
Collector<T, A, R>接受三个泛型参数,对可变减少操作的数据类型作相应限制:
T:输入元素类型
A:缩减操作的可变累积类型(通常隐藏为实现细节)
R:可变减少操作的结果类型
Collector接口声明了4个函数,这四个函数一起协调执行以将元素目累积到可变结果容器中,并且可以选择地对结果进行最终的变换:
Supplier<A> supplier() BiConsumer<A, T> accumulator() BinaryOperator<A> combiner() Function<A, R> finisher()
在Collector接口的characteristics方法内,可以对Collector声明相关约束:
Set<Characteristics> characteristics()
:
Characteristics是Collector内的一个枚举类,声明了CONCURRENT、UNORDERED、IDENTITY_FINISH等三个属性,用来约束Collector的属性:
如果一个容器仅声明CONCURRENT属性,而不是UNORDERED属性,那么该容器仅仅支持无序的Stream在多线程中执行。
collect
collect
有两个接口:
<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); 复制代码
<1> <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)
Supplier supplier是一个工厂函数,用来生成一个新的容器;
BiConsumer accumulator也是一个函数,用来把Stream中的元素添加到结果容器中;
BiConsumer combiner还是一个函数,用来把中间状态的多个结果容器合并成为一个(并发的时候会用到)
Supplier<List<String>> supplier = ArrayList::new; BiConsumer<List<String>, String> accumulator = List::add; BiConsumer<List<String>, List<String>> combiner = List::addAll; //return [aaa1, aaa1],实现了Collectors.toCollection List<String> list1 = stringCollection.stream() .filter(x -> x.startsWith("a")) .collect(supplier, accumulator, combiner); 复制代码
<2> <R, A> R collect(Collector<? super T, A, R> collector)
Collectors
是Java已经提供好的一些工具方法:
List<String> stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa1"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); 复制代码
转换成其他集合:
toList
//return [aaa1, aaa1] stringCollection.stream() .filter(x -> x.startsWith("a")).collect(Collectors.toList()) 复制代码
toSet
//return [aaa1] stringCollection.stream() .filter(x -> x.startsWith("a")).collect(Collectors.toSet()) 复制代码
toCollection
接口:
public static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) 复制代码
实现:
//return [aaa1, aaa1] List<String> list = stringCollection.stream() .filter(x -> x.startsWith("a")) .collect(Collectors.toCollection(ArrayList::new)); 复制代码
toMap
接口:
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) 复制代码
实现:
//return {aaa1=aaa1_xu} Function<String, String> xu = x -> x + "_xu"; Map<String, String> map = stringCollection.stream() .filter(x -> x.startsWith("a")) .distinct() .collect(Collectors.toMap(Function.identity(), xu)); 复制代码
转成值:
averagingDouble averagingInt averagingLong counting maxBy minBy reducing summarizingDouble summarizingInt summarizingLong summingDouble summingInt summingLong
数据分区:
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) 复制代码
实现:
Predicate<String> startA = x -> x.startsWith("a"); //return {false=[ddd2, bbb1], true=[aaa1, aaa1]} Map<Boolean, List<String>> map2 = stringCollection.stream() .collect(Collectors.partitioningBy(startA)); //return {false={false=[ddd2], true=[bbb1]}, true={false=[], true=[aaa1, aaa1]}} Predicate<String> end1 = x -> x.endsWith("1"); Map<Boolean, Map<Boolean, List<String>>> map3 = stringCollection.stream() .collect(Collectors.partitioningBy(startA, Collectors.partitioningBy(end1))); 复制代码
数据分组:
groupingBy
接口:
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,Supplier<M> mapFactory, Collector<? super T, A, D> downstream) 复制代码
实现:
//rerurn {a=[aaa1, aaa1], b=[bbb1], d=[ddd2]} Function<String, String> stringStart = x -> String.valueOf(x.charAt(0)); Map<String, List<String>> map4 = stringCollection.stream() .collect(Collectors.groupingBy(stringStart)); //rerurn {ddd2=1, bbb1=1, aaa1=2} Map<String, Long> map5 = stringCollection.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); //rerurn {d=1, a=2, b=1} Map<String, Long> map6 = stringCollection.stream() .collect(Collectors.groupingBy(stringStart, LinkedHashMap::new, Collectors.counting())); 复制代码
reduce
reduce
有三个接口:
Optional<T> reduce(BinaryOperator<T> accumulator); <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner); T reduce(T identity, BinaryOperator<T> accumulator); 复制代码
<1> Optional<T> reduce(BinaryOperator<T> accumulator)
BinaryOperator<String> binaryOperator = (x, y) -> x + y; //rerurn ddd2aaa1bbb1aaa1 String reduceStr1 = stringCollection.stream().reduce(binaryOperator).orElse(""); 复制代码
<2> T reduce(T identity, BinaryOperator<T> accumulator)
//return start:ddd2aaa1bbb1aaa1 String reduceStr2=stringCollection.stream().reduce("start:",binaryOperator); 复制代码
<3> <U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)
第一个参数返回实例u,传递你要返回的U类型对象的初始化实例u
BiFunction accumulator,负责数据的累加
BinaryOperator combiner,负责在并行情况下最后合并每个reduce线程的结果
List<Person> personList = new ArrayList<>(); personList.add(new Person(10, 20)); personList.add(new Person(20, 30)); personList.add(new Person(30, 50)); BiFunction<Person, Person, Person> biFunction = (x, y) -> new Person(x.getAge() + y.getAge(), x.getRate() + y.getRate()); BinaryOperator<Person> binaryOperator1 = (x, y) -> new Person(x.getAge() + y.getAge(), x.getRate() + y.getRate()); Person total = personList.stream().reduce(new Person(0, 0), biFunction, binaryOperator1); System.out.println("total:"+total); 复制代码
Map的双重循环
//对map的entry对象来做stream操作,使用两次forEach Map<String, Long> map = new HashMap<>(); crowdMap.entrySet().stream() .map(Map.Entry::getValue) .forEach(x -> x.entrySet().forEach(y -> { if (map.containsKey(y.getKey())) map.put(y.getKey(), map.get(y.getKey()) + y.getValue()); else map.put(y.getKey(), y.getValue()); })); //对map的entry对象来做stream操作,使用flatMap将stream合并 Map<String, Long> map = new HashMap<>(); crowdMap.entrySet().stream() .map(Map.Entry::getValue) .flatMap(x -> x.entrySet().stream()) .forEach(y -> { if (map.containsKey(y.getKey())) map.put(y.getKey(), map.get(y.getKey()) + y.getValue()); else map.put(y.getKey(), y.getValue()); }); //使用map本身的foreach语句 Map<String, Long> map = new HashMap<>(); crowdMap.forEach((key, value) -> value.forEach((x, y) -> { if (map.containsKey(x)) map.put(x, map.get(x) + y); map.put(x, y); })); 复制代码
List的多次分组
//使用groupingBy将ApproveRuleDetail对象分别按照item和detail分组,并计次 Map<String, Map<String, Long>> detailMap = approveRuleDetailList.stream() .collect(Collectors .groupingBy(ApproveRuleDetail::getItem, Collectors. groupingBy(ApproveRuleDetail::getDetail, Collectors.counting()))); 复制代码
List按照自定义条件分组
//使用自定义的Function函数,将年龄按照每10岁分组 Function<Integer, Integer> ageGroup = x -> x / 10; Map<Integer, List<StatisticsPipeline>> ageMap = statisticsPipelineList .stream() .collect(Collectors.groupingBy(y -> ageGroup.apply(y.getAge()))); 复制代码
//将年龄按不同方式分组 Function<Integer, Integer> ageCredit = x -> { if (x <= 18) return 18; else if (x >= 40) return 40; else return x; }; //将StatisticsPipeline转化为suggestion ToDoubleFunction<StatisticsPipeline> mapper = StatisticsPipeline::getSuggestion; //将人群按照不同年龄分组,并计算每个年龄段的suggestion的平均值 Map<Integer, Double> ageCreditMap = statisticsPipelineList .stream() .collect(Collectors.groupingBy(y -> ageCredit.apply(y.getAge()), Collectors.averagingDouble(mapper))); 复制代码
多个数据求集合
//合并数据 private BiFunction<Integer[], ApprovePipeline, Integer[]> accumulator = (x, y) -> new Integer[]{ x[0] + y.getAuth(), x[1] + y.getAntiFraud(), x[2] + y.getCreditRule(), x[3] + y.getModelReject(), x[4] + y.getSuggestion() }; //合并集合 private BinaryOperator<Integer[]> combiner = (x, y) -> new Integer[]{x[0] + y[0], x[1] + y[1], x[2] + y[2], x[3] + y[3], x[4] + y[4]}; //将ApprovePipeline对象的不同数据相加 Integer[] detail = approvePipelineList.stream().reduce(new Integer[]{0, 0, 0, 0, 0}, accumulator, combiner); 复制代码
多个数据求集合-多重合并
private BiFunction<Integer[], ApprovePipeline, Integer[]> accumulator = (x, y) -> new Integer[]{ x[0] += y.getAuth(), x[1] += y.getAntiFraud(), x[2] += y.getCreditRule(), x[3] += y.getModelReject(), x[4] += y.getSuggestion() }; //合并数据 BiFunction<Integer[], Map.Entry<String, List<ApprovePipeline>>, Integer[]> newAccumulator = (x, y) -> { List<ApprovePipeline> pipelineList = y.getValue(); Integer[] data = pipelineList.stream().reduce(new Integer[]{0, 0, 0, 0, 0}, accumulator, combiner); return new Integer[]{ x[0] += data[0], x[1] += data[1], x[2] += data[2], x[3] += data[3], x[4] += data[4] }; }; //最终reduce Integer[] total = channelMap.entrySet().stream().reduce(new Integer[]{0, 0, 0, 0, 0}, newAccumulator, combiner); 复制代码
map最大多项和
Long hourC3 = hourMap.entrySet().stream().mapToLong(Map.Entry::getValue).sorted().limit(3).sum(); 复制代码