美文网首页Java 8 新特性
Java 8 函数式接口(三) 四大内置的核心函数式接口的样例

Java 8 函数式接口(三) 四大内置的核心函数式接口的样例

作者: 爱恨_交加 | 来源:发表于2021-12-30 16:35 被阅读0次

Consumer<T>

对类型为 T 参数应用操作

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

样例一

探究 accept 方法

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        handleStringList(Arrays.asList(new String[]{"12", "56", "90"}), s -> {
            if(s.contains("5")) System.out.println(s);
        });
    }
    /** 定义操作方法 */
    public static void handleStringList(List<String> stringList, Consumer<String> consumer){
        for(String str : stringList) consumer.accept(str);
    }
}

输出

56

样例二

探究 andThen 方法

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        // 演示-1 传递字符串
        handleString("123",
                s -> System.out.println(s + "456"),
                s -> System.out.println(s + "789"));
        // 演示-2 传递列表
        handleList(Arrays.asList(new String[]{"123"}),
                s -> {s.set(0, s.get(0) + "456");System.out.println(s.get(0));},
                s -> {s.set(0, s.get(0) + "789");System.out.println(s.get(0));});
    }
    /** 定义操作方法-1 */
    public static void handleString(String str, Consumer<String> consumer1, Consumer<String> consumer2){
        consumer1.andThen(consumer2).accept(str);
    }
    /** 定义操作方法-2 先执行consumer1,然后再执行consumer2 */
    public static void handleList(List<String> stringList, Consumer<List<String>> consumer1, Consumer<List<String>> consumer2){
        if(CollectionUtils.isEmpty(stringList)) return;
        consumer1.andThen(consumer2).accept(stringList);
    }
}

输出

123456
123789
123456
123456789

由此可见,andThen 的作用是顺序执行


Supplier<T>

返回 T 类型的结果

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

样例

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        List<Integer> list = getNumberList(3, () -> new Random().nextInt(100));
        list.stream().forEach(System.out::println);
    }
    /** 定义操作方法 */
    public static List<Integer> getNumberList(int time, Supplier<Integer> supplier){
        List<Integer> result = new ArrayList<>();
        for(int i = 0; i < time; i++) result.add(supplier.get());
        return result;
    }
}

输出

48
37
91

Function<T, R>

对类型为 T 参数应用操作,返回 R 类型的结果

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    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;
    }
}

样例一

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        System.out.println(getStringLength("123456", s -> s.length()));
    }
    /** 定义操作方法 */
    public static Integer getStringLength(String str, Function<String, Integer> function){
        return function.apply(str);
    }
}

输出

6

样例二

探究 compose 方法

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        System.out.println(getStringLength("123456", s -> s.length(), s -> s + "7890"));
    }
    /** 定义操作方法 */
    public static Integer getStringLength(String str, Function<String, Integer> function1, Function<String, String> function2){
        return function1.compose(function2).apply(str);
    }
}

输出

10

可以看到,function2 先于 function1执行,这就是 compose 方法的作用

样例三

探究 andThen 方法

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        System.out.println(getStringLength("123456", s -> s + "7890", s -> s.length()));
    }
    /** 定义操作方法 */
    public static Integer getStringLength(String str, Function<String, String> function1, Function<String, Integer> function2){
        return function1.andThen(function2).apply(str);
    }
}

输出

10

可以看到,function1 先于 function2执行,这就是 andThen 方法的作用

提示:compose 方法和 andThen 方法的作用刚好相反

样例四

探究 identity 方法

Function.identity() 相当于 t -> t。其意图在于提高可阅读性,个人感觉挺鸡肋的,还是偏向使用 t -> t

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("I", "love", "you", "too", "~");
        // 等价于 ==> Map<String, Integer> map = stream.collect(Collectors.toMap(s -> s, String::length));
        Map<String, Integer> map = stream.collect(Collectors.toMap(Function.identity(), String::length));
        System.out.println(map);
    }
}

输出

{love=4, too=3, I=1, ~=1, you=3}

Predicate<T>

对类型为 T 参数应用操作,返回 boolean 类型的结果

@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);
    }
}

样例一

探究 testisEqual 方法

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        handleBoolean(10, s -> s > 5);
        handleBoolean(10, Predicate.isEqual(10)); // 和 Objects.equals(Object, Object) 作用相似
    }
    /** 定义操作方法 */
    public static void handleBoolean(Integer number, Predicate<Integer> predicate){
        System.out.println(predicate.test(number));
    }
}

输出

true

样例二

探究 negate,orand 方法

代码

public class TestDemo {
    /** 测试 */
    public static void main(String[] args) {
        handleBoolean(10, s -> s > 5, s -> s > 15);
    }
    /** 定义操作方法 */
    public static void handleBoolean(Integer number, Predicate<Integer> predicate1, Predicate<Integer> predicate2){
        System.out.println(predicate1.negate().test(number));
        System.out.println(predicate1.or(predicate2).test(number));
        System.out.println(predicate1.and(predicate2).test(number));
    }
}

输出

false
true
false

由此可见,其作用分别是:

  • negate:取反
  • or:短路或
  • and:短路与

上一节:Java 8 函数式接口(二) 分析、归纳内置的函数式接口
下一节:Java 8 函数式接口(四) 其它函数式接口的示例

相关文章

网友评论

    本文标题:Java 8 函数式接口(三) 四大内置的核心函数式接口的样例

    本文链接:https://www.haomeiwen.com/subject/tqsiqrtx.html