简体   繁体   English

澄清 Lambda 表达式的语法

[英]Clarifying syntax on Lambda Expression

I am using below code to sort a 2D array by column, it is taking a lambda expression in the second parameter.我使用下面的代码按列对二维数组进行排序,它在第二个参数中采用 lambda 表达式。 I don't quite understand how (a,b) is defined and how a[0] and b[0] is working in the comparator.我不太明白 (a,b) 是如何定义的,以及 a[0] 和 b[0] 如何在比较器中工作。 This code is sorting correctly, but I want to understand the syntax.此代码排序正确,但我想了解语法。 Thanks.谢谢。

   Arrays.sort(myArray, (a, b) -> Integer.compare(a[0], b[0]))

2D array by column按列排列的二维数组

Java doesn't have 2D arrays. Java 没有二维 arrays。 It has arrays of arrays, and some syntax sugar to let you declare an array-of-arrays and immediately initialize the outer array by creating new arrays and filling the slots.它具有 arrays 或 arrays 和一些语法糖,可让您声明一个数组数组并通过创建新的 arrays 并填充插槽来立即初始化外部数组。

int[][] grid = new int[10][5];

is syntax sugar for:是语法糖:

int[][] grid = new int[10][];
for (int i = 0; i < 10; i++) grid[i] = new int[5];

Arrays.sort(myArray, (a, b) -> Integer.compare(a[0], b[0]))

The type of myArray is int[][] . myArray 的类型是int[][] In other words, an array of int[] .换句话说,一个int[]数组。 Thus, to sort this, you need to provide an oracle: This oracle needs to be capable of giving consistent answers to the question: "Given 2 components (in this case, the component is int[] ), tell me if the first component sorts 'after' the second, or 'before' the second, or sorts equally. Do so by returning a negative number to indicate that the first is 'before', a positive number to indicate the first is 'after', and 0 to indicate they are equal or at least sort-ordering-wise at an equal level.因此,要对此进行排序,您需要提供 oracle:此 oracle 需要能够对以下问题给出一致的答案:“给定 2 个组件(在这种情况下,该组件是int[] ),请告诉我第一个组件是否对第二个“之后”或第二个“之前”进行排序,或平均排序。通过返回一个负数来表示第一个是“之前”,一个正数表示第一个是“之后”,以及 0 到表明它们是相等的或至少在相同的级别上排序排序。

Ordinarily, you'd do this by creating an implementation of the Comparator<int[]> interface, creating an instance of this, and passing it along:通常,您可以通过创建Comparator<int[]>接口的实现、创建 this 的实例并传递它来做到这一点:

class MySorter implements Comparator<int[]> {
    @Override public int compare(int[] a, int[] b) {
        return Integer.compare(a[0], b[0]);
    }
}

MySorter mySorter = new MySorter();
Arrays.sort(myArray, mySorter);

The above code works fine - you can compile and run it.上面的代码工作正常——你可以编译并运行它。

Lambdas aren't much different from what is happening above. Lambda 与上面发生的事情并没有太大的不同。 There is only one relevant sort method on Arrays, and it indeed does take 2 arguments: An array of T , and a Comparator that can compare T , with T being whatever you please (here, T is int[] ). Arrays 上只有一种相关sort方法,它确实需要 2 个 arguments:一个T数组和一个可以比较TComparator ,其中 T 是你喜欢的任何东西(这里, T 是int[] )。 So why can you pass a lambda there?那么为什么你可以在那里传递一个 lambda 呢?

Because the compiler works outside-in.因为编译器是由外而内工作的。 It initially just sees:它最初只是看到:

Arrays.sort(myArray, someLambdaExpressionIHaveNotLookedAtYet)

and will stop right there, and try to figure out which method is intended.并且会停在那里,并尝试找出打算使用哪种方法。 It'll find that only one method 'works': public static <T> sort (T[] array, Comparator<T> comparator) .它会发现只有一种方法“有效”: public static <T> sort (T[] array, Comparator<T> comparator)

Only then does javac continue: First, it checks that Comparator is a so-called 'single abstract method' type (a SAM type): It is;只有这样 javac 才会继续:首先,它检查 Comparator 是否是所谓的“单一抽象方法”类型(SAM 类型):它是; Comparator is an interface that defines just a single method*, which means it is a SAM type, which means you can shortcut the creation of a class that implements this interface, along with creating a new instance of this class, into a one-liner. Comparator 是一个只定义一个方法*的接口*,这意味着它是一个 SAM 类型,这意味着您可以将implements此接口的 class 的创建以及创建此 class 的新实例的快捷方式创建为单行.

Now, because java already knows what the lambda is supposed to represent (namely, an implementation for Comparator<int[]> , and it knows there is only one method that you're trying to implement (namely, public int compare(int[] a, int[] b) ), java already knows the variable types . The method you're implementing has to be int[] a, int[] b .现在,因为java 已经知道 lambda 应该代表什么(即Comparator<int[]>的实现,并且它知道您尝试实现的方法只有一种(即public int compare(int[] a, int[] b) ), java 已经知道变量类型。您要实现方法必须是int[] a, int[] b

That's why you don't have to specify it.这就是您不必指定它的原因。 You can just write (a, b) - java fills in the int[] for you.您可以只写(a, b) - java 为您填写int[] You CAN write it out: Give it shot, write Arrays.sort(myArray, (int[] a, int b[]) -> Integer.compare(a[0], b[0]) and you'll find it works exactly the same way.你可以写出来:试一试,写Arrays.sort(myArray, (int[] a, int b[]) -> Integer.compare(a[0], b[0])你会找到它工作方式完全相同。

The rest is trivial: -> is just lambda syntax, and because you don't write a { immediately afterwards, the single expression that follows the -> is just inserted as return value. rest 是微不足道的: ->只是 lambda 语法,并且因为您没有立即编写{ ,所以 -> 后面的单个表达式只是作为返回值插入。

Thus,因此,

(a, b) -> Integer.compare(a[0], b[0])

is 100% equivalent to: 100% 相当于:

public class A implements B {
    public C {
        return D;
    }
}
A a = new A();

Where:在哪里:

  • A = a randomly chosen irrelevant name, A = 随机选择的不相关名称,
  • B = the type that is expected there B = 预期的类型
  • C = a copy of the one method defined in B (and if there is not one method, you can't use this syntax), C = B 中定义的一种方法的副本(如果没有一种方法,则不能使用此语法),
  • D = whatever you wrote after the ->. D = 你在 -> 之后写的任何内容。

*) Methods that are already defined in java.lang.Object don't count, and methods with default impls also don't count. *) 已在 java.lang.Object 中定义的方法不计算在内,具有默认实现的方法也不计算在内。

Arrays.sort(T[] a, Comparator<? super T> c) takes a Comparator<T> as the second argument, which declares the method int compare(T o1, T o2) . Arrays.sort(T[] a, Comparator<? super T> c)Comparator<T>作为第二个参数,它声明了方法int compare(T o1, T o2)

That means the lambda expression must implement that method, and with myArray being an Integer[][] or int[][] , it means that T is an Integer[] or int[] , so both a and b are Integer[] or int[] .这意味着 lambda 表达式必须实现该方法,并且myArrayInteger[][]int[][] ,这意味着TInteger[]int[] ,所以ab都是Integer[]int[]

The statement will therefore sort the 2D array by the first column.因此,该语句将按第一列对二维数组进行排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM