java8四大核心函数式接口及reduce方法

1、java8提供的函数式接口基本能满足我们的任务开发

package com.dw;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.*;
import java.util.stream.Collectors;

public class DemoFunction {
    /** ============================ 四大核心内置函数接口 ============================== */

    // Consumer<T> , void accept(T t);
    @Test
    public void testConsumer() {
        // example 1
        List<String> list = Arrays.asList("hello world", "welcome china", "how are you");
        list.stream().forEach((str) -> System.out.println(str));

        // example 2
        consumerT("this is my consumer example 2", (str) -> System.out.println(str));
    }

    public void consumerT(String str, Consumer t) {
        t.accept(str);
    }

    // Supplier<T> , T get();
    @Test
    public void testSupplier() {
        // example 1
        System.out.println(supplierT(() -> "test supplier!"));
    }

    public String supplierT(Supplier t) {
        return (String) t.get();
    }

    //Function<T, R> , R apply(T t);
    @Test
    public void testFunction() {
        // example 1
        List<User> list = new ArrayList<>();
        list.add(new User("张三" ,111));
        System.out.println(list.stream().map(user -> user.getName()).collect(Collectors.toList()));

        // example 2
        System.out.println(functionT(new User("王五", 222), user -> user.getName()));
    }

    public String functionT(User user, Function<User, String> t) {
        return t.apply(user);
    }


    //Predicate<T> , boolean test(T t);
    @Test
    public void testPredicate() {
        // example 1
        List<Integer> list = Arrays.asList(3,5,2,1,-2,0,10);
        System.out.println(list.stream().filter(tmp -> tmp > 0).collect(Collectors.toList()));

        // example 2
        System.out.println(predicateT(10, tmp -> tmp.equals(0)));
        System.out.println(predicateT(0, tmp -> tmp.equals(0)));
    }

    public boolean predicateT(int tmp, Predicate t) {
        return t.test(tmp);
    }

    /** ============================ 其他内置函数接口 ============================== */

    // BiFunction<T, U, R> , R apply(T t, U u); 三个参数类型可以不一样, ===>文档定义类型: BiFunction<U,? super T,U>
    @Test
    public void testBiFunction() {
        // example 1
        System.out.println(biFunctionT(333, "戴维", (name, id) -> new User(name, id)));
    }

    public User biFunctionT(int i, String str, BiFunction<String, Integer, User> t) {
        return t.apply(str, i);
    }

    // BinaryOperator<T> , T apply(T t, T t);  继承至BiFunction,与BiFunction的区别在于 限定了三个参数类型一致
    @Test
    public void testBinaryOperator() {
        // example 1
        System.out.println(binaryOperatorT(10, 20, (a, b) -> a * b));
    }

    public int binaryOperatorT(int a, int b, BinaryOperator<Integer> t) {
        return t.apply(a, b);
    }

    // UnaryOperator<T> , T apply(T t); (Function子接口),对参数T进行一元操作,返回T类型
    @Test
    public void testUnaryOperator() {
        // example 1
        System.out.println(unaryOperatorT("HELLO world !", str -> str.toUpperCase()));
    }
    public String unaryOperatorT(String str, UnaryOperator<String> t) {
        return t.apply(str);
    }

    // BiConsumer<T, U> ,Consumer<T>的变种
    @Test
    public void testBiConsumer() {
        // example 1
        biConsumerT(444,  "hello world !", (a, s) -> System.out.println(a + " " + s));
    }

    public void biConsumerT(int a, String s, BiConsumer<Integer, String> t) {
        t.accept(a, s);
    }

    // ToIntFunction<T>, ToLongFunction<T>, ToDoubleFunction<T>, 分别返回int, long, double类型
    @Test
    public void testToIntFunction() {
        // example 1
        System.out.println(toIntFunctionT(new User("李四", 555), user -> user.getId()));
    }
    public int toIntFunctionT(User user, ToIntFunction<User> t) {
        return t.applyAsInt(user);
    }

    // IntFunction<T>, LongFunction<T>, DoubleFunction<T>, 参数分别为int, long, double, 返回类型T
    @Test
    public void testIntFunction() {
        // example 1
        System.out.println(intFunctionT(666, id -> new User("马斯", id)));
    }
    public User intFunctionT(int id, IntFunction<User> t) {
        return t.apply(id);
    }

}

2、reduce 方法:经过处理得到具体的一个值(先展示用法)

    /** ============================ reduce函数 ============================== */

    /**
     * reduce有三类, 分别是一个参数, 两个参数, 三个参数
     * 1、两个参数较一个参数多了一个初始值
     * 2、三个参数较两个参数多了一个并行操作时用于合并操作的函数时接口对象, 因此当串行操作时与两个参数的效果一致
     */

    // 一个参数
    @Test
    public void testReduce1() {
        List<Integer> list = Arrays.asList(3, 2, 4, 1);
        System.out.println(list.stream().reduce((acc, tmp) -> acc + tmp).get());
    }

    // 两个参数
    @Test
    public void testReduce2() {
        List<Integer> list = Arrays.asList(3, 2, 4, 1);
        System.out.println(list.stream().reduce(100, (acc, tmp) -> acc + tmp).intValue());
    }

    // 三个参数
    @Test
    public void testReduce3() {
        // 串行操作
        List<Integer> list = Arrays.asList(3, 2, 4, 1);
        System.out.println(list.stream().reduce(100
                , (acc, tmp) -> acc + tmp
                , (a, b) -> a + b).intValue());  // out ==> 110

        // 并行操作
        System.out.println(list.stream().parallel().reduce(100
                , (acc, tmp) -> acc + tmp
                , (a, b) -> a + b).intValue());  // out ==> 410
        /**
         * 分析:
         * list集合中四个值并行执行, 分别与初始值100相加后, 再进行合并操作, 即:
         * 1)3+100=103, 2+100=102, 4+100=104, 1+100=101
         * 2)103+102+104+101=410
         */
    }

官方文档解释:

1)一个参数:

Optional<T> reduce(BinaryOperator<T> accumulator)

使用associative累积函数对此流的元素执行reduction ,并返回描述减小值(如果有的话)的Optional 。 这相当于:

   boolean foundAny = false; T result = null; for (T element : this stream) { if (!foundAny) { foundAny = true; result = element; } else result = accumulator.apply(result, element); } return foundAny ? Optional.of(result) : Optional.empty();  

但不限于顺序执行。

2)两个参数:(第一个参数相当于初始值)

T reduce(T identity,
         BinaryOperator<T> accumulator)

使用提供的身份值和associative累积功能对此流的元素执行reduction ,并返回减小的值。 这相当于:

   T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;  

但不限于顺序执行。

3)三个参数:(串行和并行操作)

a、串行操作,效果与两个参数处理结果相同

b、并行操作,将每个accumulator处理的值,再通过combiner进行融合

<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator,
             BinaryOperator<U> combiner)

执行reduction在此流中的元素,使用所提供的身份,积累和组合功能。 这相当于:

   U result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;  

但不限于顺序执行。

猜你喜欢

转载自blog.csdn.net/ldw201510803006/article/details/82955789