美文网首页
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 继续研究

    lambda可以隐藏return 简洁的代码 常见的函数式接口 函数式接口可以有多个默认方法,但是只能有一个抽象方...

  • 继续研究

    今天主动聊了几个同学,大涵涵,小猪猪,楠楠,莎莎和阳阳。还聊了一个意向启磊,我在尝试的去推广淘小铺。目前还没有效果...

  • 深入Java基础(四)--哈希表(2)HashTable与Has

    又突然想看源码了,继续深入Java基础系列。今天是研究JavaAPI的HashTable和HashSet(顺带讨论...

  • InterValue项目双周报:20200518-2020053

    一、InterValue开发进度 1、INVE主网:研究Matlab算法封装测试库问题;继续测试Java直接调用M...

  • JAVA8你只需要知道这些(2)

    前言 上篇文章我们讲了JAVA8中接口和匿名内部类的一些新特性。这篇文章我们将继续深入的研究JAVA8。 1.Fu...

  • 继续研究烤核桃

    上次说到用中火烤核桃,五分钟后出炉,虽然比前两次烤的好吃许多,但貌似有点不太熟,再烤一次! 这次依旧用中火,时间十...

  • Java泛型的学习和使用

    前面,由于对泛型擦除的思考,引出了对Java-Type体系的学习。本篇,就让我们继续对“泛型”进行研究: JDK1...

  • 水彩人物

    继续研究水彩……

  • 程序日记2018-05-20

    思考 怎样才能去深圳?要先有房··· 今天继续研究cmswing。昨天的hooks算是研究了比较彻底。今天继续研究...

  • Java学习:详解字节码class文件

    背景:通过上一篇查看字节码文件知道如何查看java字节码文件后,可以继续仔细研究下字节码文件的内容,看看里面究竟承...

网友评论

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

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