Java8| Lambda Expression
by Botao Xiao
Lambda Expression
Lambda表达式是一种简洁的表示可传递的匿名函数的一种方法:它没有名称,但是它有参数列表,函数主体,返回类型还能抛出异常列表。 匿名: 没有明确的名称。 函数: 不像方法属于某个特定的类。 传递: Lambda表达式可以作为参数传递给方法或储存在变量中。 简洁:无需像匿名类写很多模板代码。
Lambda表达式的构成
private Comparator<Apple> comparator =
(Apple a1, Apple a2) -> a1.getWeight() - a2.getWeight();
- 括号:参数列表
- 箭头: 将参数列表和Lambda主体分隔开
- Lambda主体:具体的函数给出返回值
Lambda表达式的语法
- (parameters) -> expression: 默认expression为返回值。
- (parameters) ->{statements;}: 在花括号之中填充行为。
Lambda的使用位置
在函数式接口(一个只定义一个抽象方法的接口)上使用抽象方法。Lambda表达式允许直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。
Lambda表达式的实现
- 行为参数化:所谓的行为参数化是一种策略模式的体现。将一个函数式接口作为一种行为作为参数传递给另一个方法。此时p就是一种行为,对于文件的处理是不固定的,根据接口的实现类而定。典型的策略模式。当前例子中体现在参数FileReaderProcessor p。
public static String processFile(String file, FileReaderProcessor p) throws IOException { File f = new File(file); try(BufferedReader br = new BufferedReader(new FileReader(f))) { return p.process(br); } }
- 使用函数式接口传递行为。@FunctionalInterface,该接口中只有一个抽象方法。
@FunctionalInterface public interface FileReaderProcessor { String process(BufferedReader br) throws IOException; }
- 执行行为。此时的行为是不确定的,需要传入策略。
return p.process(br);
- 传递Lambda。此处的lambda充当接口的实现类。
public static void main(String[] args) throws IOException { System.out.println(processFile("E:\\LocalProject\\Concurrent\\src\\main\\java\\ca\\mcmaster\\concurrent\\pojo\\UserInfo.java", (BufferedReader br) -> { return br.readLine() + br.readLine() + br.readLine(); })); }
Java8中新增的函数式接口
- Predicate
:判断是否满足条件, 用于添加判断条件。 @FunctionalInterface public interface Predicate<T> { /** *Evaluates this predicate on the given argument. *@param t the input argument *@return {@code true} if the input argument matches the predicate, *otherwise {@code false} */ boolean test(T t); }
- Consumer
: 其中有一个accept方法,用于对某个元素进行操作,无返回值。 public interface Consumer<T> { /** *Performs this operation on the given argument. *@param t the input argument */ void accept(T t); } // 对于每个元素而言,操作是隐藏的。 public static <T> void processList(List<T> list, Consumer<T> c){ for(T t : list) c.accept(t); } List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8); processList(list, (Integer i) -> System.out.println(i)); //实际的行为是打印每一个元素。
- Function<T, R>: 其中有一个apply方法,可以接受泛型参数并且定义返回值R类型。这种方法是Consumer方法的延伸,从无返回类型变成了又返回类型。
@FunctionalInterface public interface Function<T, R> { /** *Applies this function to the given argument. *@param t the function argument *@return the function result */ R apply(T t); } public class MyFunctionInterface { public static <T, R> List<R> process(List<T> list, Function<T, R> f){ List<R> result = new LinkedList<>(); for(T t : list) result.add(f.apply(t)); return result; } public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8); List<Integer> result = process(list, (Integer i) -> {return i + 1;}); for(Integer integer : result) System.out.println(integer); } }
- Supplier
: 提供对象的函数接口 @FunctionalInterface public interface Supplier<T> { /** *Gets a result. *@return a result */ T get(); } public class MyFunctionInterface { public static <T> List<T> createList(Supplier<T> s){ List<T> result = new LinkedList<>(); for(int i = 0; i < 10; i++){ result.add(s.get()); } return result; } public static void main(String[] args) { List<String> str = createList(() -> new String("12234")); for (String ss : str) System.out.println(ss); } }
方法引用
方法的引用允许我们重复使用现有的方法定义,并向Lambda一样传递它们。
构建方法的引用
- 指向静态方法的引用。
- 指向任意类型实例方法的方法引用。你在引用一个对象的方法,而这个对象本身是Lambda的一个参数。
- 指向现有对象的实例方法的引用。在Lambda中引用一个已经存在的外部对象中的方法。
构造函数的引用
- 无参构造器,使用Supplier
的方法。 public class MyFunctionInterface { public static <T> List<T> createList(Supplier<T> s){ List<T> result = new LinkedList<>(); for(int i = 0; i < 10; i++){ result.add(s.get()); } return result; } public static void main(String[] args) { List<String> str = createList(String::new); //引用无参构造方法 for (String ss : str) System.out.println(ss); } }
- 引用带有参数的构造器,使用Function<T,R>函数接口
public static <T, R> R createObject(T t, Function<T, R> f){ return f.apply(t); } public static void main(String[] args) { // 调用了String的带有一个参数的构造器 String s = createObject("Test", String::new); System.out.println(s); }
- 带有多个参数的构造器,使用BiFunction<T, U, R>函数接口。
public static <T, U, R> R createObject(T t, U u, BiFunction<T, U, R> f){ return f.apply(t, u); } public static void main(String[] args) { String s = createObject("Test", String::new); Apple apple = createObject(123, "Apple", Apple::new); System.out.println(apple.toString()); }
复合
比较器的复合Comparator
- 逆序, 使用reversed方法。
default Comparator<T> reversed() { return Collections.reverseOrder(this); }
- 链式比较器, thenComparing
default Comparator<T> thenComparing(Comparator<? super T> other) { Objects.requireNonNull(other); return (Comparator<T> & Serializable) (c1, c2) -> { int res = compare(c1, c2); return (res != 0) ? res : other.compare(c1, c2); }; }
谓词复合 Predicate
- 非 negate()
Predicate<Apple> notRedApple = redApple.negate();
- 与 and()
Predicate<Apple> redAndHeavyApple = redApple.and(a -> a.getWeight() > 150);
- 或 or()
Predicate<Apple> redAndHeavyAppleOrGreen = redApple.and(a -> a.getWeight() > 150).or(a -> "green".equals(a.getColor()));
函数复合 Function<T, R>中函数使用
- andThen()
public static <T, R> R apply(T t, Function<T, R> f){ return f.apply(t); } public static void main(String[] args) { Function<Integer, Integer> f = t -> {return t + 1;}; Function<Integer, Integer> g = t -> {return t * 2;}; Function<Integer, Integer> h = f.andThen(g); // f(g(x)) Integer res = apply(1, h); System.out.println(res); }
- compose()
public static <T, R> R apply(T t, Function<T, R> f){ return f.apply(t); } public static void main(String[] args) { Function<Integer, Integer> f = t -> {return t + 1;}; Function<Integer, Integer> g = t -> {return t * 2;}; Function<Integer, Integer> h = f.compose(g); // g(f(x)) Integer res = apply(1, h); System.out.println(res); }
引用
Subscribe via RSS