美文网首页
Java Lambda-2 继续研究

Java Lambda-2 继续研究

作者: 巴巴11 | 来源:发表于2020-03-22 20:05 被阅读0次

    lambda可以隐藏return

    简洁的代码

    Comparator<Apple> comparator = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
    Comparator<Apple> comparator1 = new Comparator<Apple>() {
                @Override
                public int compare(Apple o1, Apple o2) {
                    return o1.getWeight().compareTo(o2.getWeight());
                }
            };
    

    常见的函数式接口

    函数式接口可以有多个默认方法,但是只能有一个抽象方法。

    @FunctionalInterface只是一个标志符号,并不是必须的。就像@Override标注。

    @FunctionalInterface
    public interface Predicate<T> {
      boolean test(T t);
    }
    
    @FunctionalInterface
    public interface Comparator<T> {
        int compare(T o1, T o2);
    }
    
    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    
    @FunctionalInterface
    public interface Callable<V> {  
        V call() throws Exception;
    }
    
    image.png
    image.png

    任何函数式接口都不允许抛出受检异常( checked exception)。
    如果需要Lambda表达式来抛出异常, 有两种办法:
    定义一个自己的函数式接口,并声明受检异常,或者把Lambda包在一个try/catch块中。
    比如,一个新的函数式接口BufferedReaderProcessor,它显式声明了一个IOException:

    @FunctionalInterface
    public interface BufferedReaderProcessor {
    String process(BufferedReader b) throws IOException;
    }
    BufferedReaderProcessor p = (BufferedReader br) -> br.readLine();
    显式捕捉受检异常:
    Function<BufferedReader, String> f = (BufferedReader b) -> {
    try {
      return b.readLine();
    }
    catch(IOException e) {
      throw new RuntimeException(e);
    }
    };
    

    Lambda表达式引用的局部变量必须是最终的( final)

    可以把方法引用看作针对仅仅涉及单一方法的Lambda的语法糖

    如何构建方法引用

    方法引用主要有三类。
    (1) 指向静态方法的方法引用(例如Integer的parseInt方法, 写作Integer::parseInt)。
    (2) 指向任意类型实例方法的方法引用 ( 例 如 String 的 length 方 法 , 写 作
    String::length)。
    (3) 指向现有对象的实例方法的方法引用(假设你有一个局部变量expensiveTransaction
    用于存放Transaction类型的对象,它支持实例方法getValue,那么你就可以写expensiveTransaction::getValue)。
    

    总结:

    
    Lambda表达式可以理解为一种匿名函数:它没有名称,但有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常的列表。
    Lambda表达式让你可以简洁地传递代码。
    
    函数式接口就是仅仅声明了一个抽象方法的接口。
    
    只有在接受函数式接口的地方才可以使用Lambda表达式。
    
    Lambda表达式允许你直接内联,为函数式接口的抽象方法提供实现,并且将整个表达式作为函数式接口的一个实例。
    
    Java 8自带一些常用的函数式接口,放在java.util.function包里,包括Predicate<T>、 Function<T,R>、 Supplier<T>、 Consumer<T>和BinaryOperator<T>等。
    
    为了避免装箱操作,对Predicate<T>和Function<T, R>等通用函数式接口的原始类型特化: IntPredicate、 IntToLongFunction等。
    
    环绕执行模式(即在方法所必需的代码中间,你需要执行点儿什么操作,比如资源分配和清理)可以配合Lambda提高灵活性和可重用性。
    
    Lambda表达式所需要代表的类型称为目标类型。
    
    方法引用让你重复使用现有的方法实现并直接传递它们。
    
    Comparator、 Predicate和Function等函数式接口都有几个可以用来结合Lambda表达式的默认方法。
    

    代码

    package com.hw;
    
    import java.util.*;
    import java.util.function.*;
    
    import static java.util.stream.Collectors.groupingBy;
    import static java.util.stream.Collectors.toList;
    
    public class Main {
    
        public static void main(String[] args) {
            List<Apple> lists = Arrays.asList(new Apple[]{
                    new Apple(10),  new Apple(20), new Apple(30)
            });
    
            /*Collections.sort(lists, new Comparator<Apple>() {
                @Override
                public int compare(Apple o1, Apple o2) {
                    return o1.getWeight().compareTo(o2.getWeight());
                }
            });*/
    
            // 方法引用
            lists.sort(Comparator.comparing(Apple::getWeight));
            lists.sort(Comparator.comparing(Apple::getWeight).reversed()); // 逆序排列
            lists.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
    
            List<String> str = Arrays.asList("a","b","A","B");
            str.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
            str.sort(String::compareToIgnoreCase);
    
            Function<String, Integer> function1 = (String s) -> s.length();
            Function<String, Integer> function2 = String::length;
    
            BiPredicate<List<String>, String> c1 = List::contains;
    
            // 构造函数引用
            Supplier<Apple> s1 = () -> new Apple();
            Apple aa1 = s1.get();
    
            Supplier<Apple> s2 = Apple::new;
            Apple aa = s2.get();
    
            Function<Integer, Apple> fu11 = (a) -> new Apple(a);
            Apple ab11 = fu11.apply(11);
    
            Function<Integer, Apple> fu1 = Apple::new;
            Apple ab1 = fu1.apply(11);
    
            BiFunction<Integer, String, Apple> fu111 = (a, b) -> new Apple(a, b);
            Apple ab111 = fu111.apply(11, "test");
    
            BiFunction<Integer, String, Apple> fua1 = Apple::new;
            Apple aba1 = fua1.apply(11, "test");
    
            // 比较器链
            lists.sort(Comparator.comparing(Apple::getName).reversed().thenComparing(Apple::getWeight));
    
            // 谓词复合
            // 谓词接口包括三个方法: negate、 and和or
            Predicate<Apple> predicate11 = (a) -> a.getWeight() > 10;
            Predicate<Apple> predicate111 = predicate11.negate(); // 非
            Predicate<Apple> predicate12 =
                    predicate11.and((a) -> a.getName().equals(""))
                                .or((a) -> a.getWeight() < 100);
    
    
            lists.stream().forEach(l -> System.out.println(l.getWeight()));
    
            List<Apple> lists1 = Arrays.asList(new Apple[]{
                    new Apple(10, "aa"),  new Apple(20, "bb"), new Apple(30, "cc"),
                    new Apple(10, "dd"),  new Apple(20, "b1")
            });
    
            // 函数复合
            // 流水线式操作
            Function<Integer, Integer> f = x -> x + 1;
            Function<Integer, Integer> g = x -> x * 2;
            Function<Integer, Integer> h = f.andThen(g); // g(f(x))
            Function<Integer, Integer> h1 = f.compose(g); // f(g(x))
    
    
            Map<Integer, List<Apple>> map =
                    lists1.stream().filter(l -> l.getWeight() > 1)
                            .collect(groupingBy(Apple::getWeight));
            for(Map.Entry<Integer, List<Apple>> entrySet : map.entrySet()) {
                System.out.println(entrySet.getValue().toString());
            }
    
            List<Apple> l1 = lists1.stream().collect(toList());
            List<String> l2 = lists1.stream().map(Apple::getName).collect(toList());
    
            Comparator<Apple> comparator = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
            Comparator<Apple> comparator1 = new Comparator<Apple>() {
                @Override
                public int compare(Apple o1, Apple o2) {
                    return o1.getWeight().compareTo(o2.getWeight());
                }
            };
    
            Function<String, Integer> func1 = (String s) -> s.length();
            Function<Apple, Boolean> func2 = (Apple a) -> a.getWeight() > 100;
            /*Consumer<Integer> co = (int x, int y) -> {
                System.out.println(x + y);
                System.out.println(x - y);
            };*/
            Supplier<Integer> supplier = () -> 10;
    
            // 同一个Lambda可用于多个不同的函数式接口
            Comparator<Apple> comparator2 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
            BiFunction<Apple, Apple, Integer> biFunction = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
            ToIntBiFunction<Apple, Apple> biFunction1 = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
    
            Runnable runnable = () -> System.out.println("11");
            Runnable runnable1 = new Runnable() {
                @Override
                public void run() {
                    System.out.println("11");
                }
            };
    
        }
    }
    

    相关文章

      网友评论

          本文标题:Java Lambda-2 继续研究

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