Android 第一行代码(3版) - kotlin - Lam

2023-02-18  本文已影响0人  刚刚8888

由来:
Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的「λ演算」得名,直接对应于其中的lambda抽象(lambda abstraction)。
λ这个符号读lambda,所以匿名函数又被称为lambda函数,最早lambda函数应该是出现Lisp中的,因为它是一门「纯函数式编程的语言」。
λ演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义、函数如何被应用以及递归的形式系统。

它是java从函数式编程语言借鉴,方便开发人员编写清晰、高效代码的一种编程风格。
java8中从函数式编程引入了两个核心思想:方法(方法引用)和lambda表达式可以作为值传递,并且函数或者方法可以有效、安全地并行执行。

Lambda 在编程语言中往往是一个匿名函数,也就是说Lambda 是一个抽象概念,而编程语言提供了配套支持,比如在 Java 中其实为Lambda 进行配套的就是函数式接口,通过函数式接口生成匿名类和方法进行Lambda 式的处理。

栗子:

// 苹果
public class Apple {
    private String color;
    // Apple类中行为参数化
    public interface ApplePredicate {
        boolean filter(Apple apple);
    }
    // Apple类中用来筛选属性的方法
     public static List<Apple> filter(List<Apple> apples, ApplePredicate predicate) {
            List<Apple> filterList = new ArrayList<>();
            for (Apple apple : apples) {
                if (predicate.filter(apple)) {
                    filterList.add(apple);
                }
            }
            return filterList;
     }
}

List<Apple> apples = new ArrayList<Apple>();
...
// => 传统遍历
// => 筛选出列表中颜色为绿色的苹果
 List<Apple> greenApples = new ArrayList<>();
 for (Apple apple : apples) {
    if ("green".equals(apple.getColor())) {
            greenApples.add(apple);
         }
  }

// => 3种实现方式
// 1. ApplePredicate实现类
 public class GreenApplePredicate implements ApplePredicate {
        @Override
        public boolean filter(Apple apple) {
            return "green".equals(apple.getColor());
        }
 }
List<Apple> f1 = Apple.filter(apples, new GreenApplePredicate());
// 2. 匿名内部类
List<Apple> f2 = Apple.filter(apples, new ApplePredicate() {
        @Override
        public boolean filter(Apple apple) {
            return "green".equals(apple.getColor());
        }
 });
// 3.  lambda表达式
List<Apple> f3 = Apple.filter(apples
                      , (Apple apple) -> "green".equals(apple.getColor()));

lambda函数优缺点

Java中使用

// 1. 不需要参数,返回值为 5  
() -> 5  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s) 

栗子:
// 无参无返回值
TestA testA = () -> System.out.print("无参无返回值\n");
testA.exec();
// 无参有返回值
TestB testB = () -> "无参有返回值\n";
System.out.print(testB.exec());
// 有参无返回值
TestBB testBB = (String s) -> System.out.print(s);
testBB.exec("有参无返回值\n");
// 有参有返回值
TestC testC = (String a, String b) -> a + b;
System.out.print(testC.exec("2个参数", "有返回值\n"));
// 不可移至尾部
textD(1, 2, (int x, int y) -> x + y);
// 局部变量截获
NumAdd a = add();
System.out.print(a.exec(10) + "\n");
System.out.print(a.exec(20) + "\n");

int total = 0;
private NumAdd add() {
    //int total = 0;
    //可以捕获局部变量,但不能对局部变量修改,默认是final类型
    return (int num) -> {
        total += num;
        return total;
    };}
private void textD(int p1, int p2, Fn fn) { 
    System.out.print(fn.exec(p1, p2) + "\n");}
public interface TestA { void exec(); }
public interface TestB { String exec(); }
public interface TestBB { void exec(String s); }
public interface TestC { String exec(String a, String b); }
public interface Fn { int exec(int a, int b); }
public interface NumAdd { int exec(int num); }

kotlin中使用

//表示无参数无返回值的Lambda表达式类型
{() -> Unit}
//表示接收一个T类型参数,无返回值的Lambda表达式类型
{(T) -> Unit}
//表示接收一个T类型参数,返回一个R类型值的Lambda表达式类型
{(T) -> R}
//表示接收一个T类型和P类型的参数,返回一个R类型值的Lambda表达式类型
{(T, P) -> R}
//表示接收一个T类型参数和一个接收P、Q类型两个参数并返回一个S类型的值的Lambda表达式类型参数
//,返回一个R类型值的Lambda表达式类型
{(T, (P,Q) -> S) -> R}

栗子:
// 无参无返回值
val testA = { print("无参无返回值\n") }
testA()
// 无参有返回值
val testB = { "无参有返回值\n" }
print(testB())
// 有参无返回值
val testBB: (String) -> Unit = { print(it) }
testBB("有参无返回值\n")
// 有参有返回值
val testC = { strA: String, strB: String 
              -> strA + strB }
print(testC("2个参数", "有返回值\n"))
// 最后一个参数是lambda表达式, 可移至尾部
textD(1, 2) { x: Int, y: Int -> x + y}
// 局部变量截获
val a = add()
print(a(10).toString() + "\n")
print(a(20).toString() + "\n")

fun add() : (Int) -> Int {
    var total = 0
    return { num: Int -> total += num
        total
    }}
fun textD(p1: Int, p2:Int ,fn: (Int, Int) -> Int) {
    print(fn(p1, p2).toString() + "\n")}

规则:
java:

kotlin:

不同语言中的lambda

// =>Python
lambda [arg1[,arg2,arg3....argN]]:expression
// 栗子:
add2 = lambda x,y:x+y 
print add2(1,2)     #3
sum2 = lambda x,y=10:x+y
print sum2(1)       #11 
print sum2(1,100)   #101

// =>C++
[ capture clause ] (parameters) -> return-type  {  definition of method  }
// 栗子:
void func(std::vector<int>& v) {  
     std::for_each(v.begin(), v.end(), [](int i) {  
            cout << i << endl; 
     });
}

// => Javascript
(p1 [,p2,p3,....pn]) => { code block  }
// 栗子:
let func  = x => x * x;
func(2) #4

// => OC  - Block 类似lambda
^返回值 参数列表 表达式
// 栗子:
void (^blockTest)(void) = ^{
    NSLog(@"block");
};
blockTest();
// 带参
^(int a){
     NSLog(@"block的使用");
};
// 不带参
^{
     NSLog(@"最简捷的block的使用");
};
// block作为参数
void funcWithParm(void (^block)(int parm))
{
    block(10);
}

// swift 闭包
// 无参无返回值
let testA = { print("无参无返回值闭包") }
testA()
// 无参有返回值
let testB = { return "无参有返回值闭包" }
print(testB())
// 有参有返回值
let testC = {(strA: String, strB: String) 
              in return strA + strB }
print(testC("2个参数", "有返回值闭包"))
// 尾随闭包
textD(p1: 1, p2: 2) { 
   return $0 + $1    // #3 
} 
func textD(p1: Int, p2:Int ,fn: (Int, Int) -> Int) {
    print(fn(p1, p2))
}
// 闭包可能捕获非常量变量
let a = add();
print(a(10))        // # 10
print(a(20))        // # 30
func add() -> (Int) -> Int {
    var total = 0
    return {num in
        total += num;
        return total;
    }
}

函数式接口

// forEach 参数类型
@FunctionalInterface 
public interface Consumer<T> {  
   void accept(T t);
}
public interface Iterable<T> {
  ...
   default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
}

// 栗子:
List<Integer> list = Arrays.asList(1,2,3,4);
list.forEach(item -> {
     System.out.print(item);
});
// =>
list.forEach(System.out::println);
// collect 参数类型
@FunctionalInterface
public interface Supplier<T> {
    T get();
}
public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
 }
public interface Stream<T> extends BaseStream<T, Stream<T>> {
    ...
    <R, A> R collect(Collector<? super T, A, R> collector);
}
// 栗子:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
List<Integer> newNumbers = numbers.stream()
            .filter(x -> x >= 2)
            .collect(Collectors.toList()); // 将大于等于2的数重新收集成一个集合
// map 参数类型
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    ...
}
public interface Stream<T> extends BaseStream<T, Stream<T>> {
    ...
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    T reduce(T identity, BinaryOperator<T> accumulator);
}
// 栗子:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
List<Integer> doubleNumbers = numbers.stream()
                .map(number -> number * 2)
                .collect(Collectors.toList());

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
Integer sum = numbers.stream()
          .reduce(0, (a, b) -> a + b);

// reduce 参数类型
@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
    ...
}
// filter参数类型
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    ...
}
public interface Stream<T> extends BaseStream<T, Stream<T>> {
    ...
    Stream<T> filter(Predicate<? super T> predicate);
}

Stream表达式
Stream,就是JDK8又依托于函数式编程特性为集合类库做的一个类库,它其实就是jdk提供的函数式接口的最佳实践。它能让我们通过lambda表达式更简明扼要的以流水线的方式去处理集合内的数据,可以很轻松的完成诸如:过滤、分组、收集、归约这类操作。

其中Stream的操作大致分为两类

Lambda原理

上一篇 下一篇

猜你喜欢

热点阅读