Answers:
Lambda纯粹是一个调用站点构造:lambda的接收者不需要知道Lambda涉及到,而是接受具有适当方法的Interface。
换句话说,您定义或使用一个功能接口(即具有单个方法的接口)来接受并准确返回您想要的内容。
为此,Java 8附带了一组常用的接口类型java.util.function
(感谢Maurice Naftalin提供有关JavaDoc的提示)。
对于这种特定的用例,java.util.function.IntBinaryOperator
只有一个int applyAsInt(int left, int right)
方法,因此您可以这样编写method
:
static int method(IntBinaryOperator op){
return op.applyAsInt(5, 10);
}
但是您也可以定义自己的接口并像这样使用它:
public interface TwoArgIntOperator {
public int op(int a, int b);
}
//elsewhere:
static int method(TwoArgIntOperator operator) {
return operator.op(5, 10);
}
使用您自己的界面的优点是您可以使用更清楚地表明意图的名称。
(int a, int b, int c)
了TwoArgIntOperator
。如果TwoArgIntOperator
具有相同签名的两个方法会发生什么。这个答案令人困惑。
要使用Lambda表达式,您需要创建自己的功能接口或将Java功能接口用于需要两个整数并作为值返回的操作。IntBinaryOperator
使用用户定义的功能界面
interface TwoArgInterface {
public int operation(int a, int b);
}
public class MyClass {
public static void main(String javalatte[]) {
// this is lambda expression
TwoArgInterface plusOperation = (a, b) -> a + b;
System.out.println("Sum of 10,34 : " + plusOperation.operation(10, 34));
}
}
使用Java功能界面
import java.util.function.IntBinaryOperator;
public class MyClass1 {
static void main(String javalatte[]) {
// this is lambda expression
IntBinaryOperator plusOperation = (a, b) -> a + b;
System.out.println("Sum of 10,34 : " + plusOperation.applyAsInt(10, 34));
}
}
我创建的其他示例在这里
IntBinaryOperator
文档的链接已失效。
对于不超过2个参数的函数,可以在不定义自己的接口的情况下传递它们。例如,
class Klass {
static List<String> foo(Integer a, String b) { ... }
}
class MyClass{
static List<String> method(BiFunction<Integer, String, List<String>> fn){
return fn.apply(5, "FooBar");
}
}
List<String> lStr = MyClass.method((a, b) -> Klass.foo((Integer) a, (String) b));
在中BiFunction<Integer, String, List<String>>
,Integer
和String
是其参数,并且List<String>
是其返回类型。
对于仅具有一个参数的函数,可以使用Function<T, R>
,其中T
参数的类型为,R
返回值的类型为。有关Java已经提供的所有接口,请参考此页面。
从http://lambdafaq.org/lambda-resources链接到一个支持Lambda的Java 8 JavaDocs的公共Web访问版本。(显然,这应该是对Joachim Sauer的回答的评论,但是我无法进入我的SO帐户并需要添加评论。) -lambda问题。
注意:此答案是在Java 8 GA文档公开可用之前编写的。不过,我仍然留在原地,因为Lambda FAQ对于学习Java 8中引入的功能的人们可能仍然有用。
对我来说,最有意义的解决方案是定义一个Callback
接口:
interface Callback {
void call();
}
然后将其用作您要调用的函数中的参数:
void somewhereInYourCode() {
method(() -> {
// You've passed a lambda!
// method() is done, do whatever you want here.
});
}
void method(Callback callback) {
// Do what you have to do
// ...
// Don't forget to notify the caller once you're done
callback.call();
}
Lambda不是特殊的接口,类或您可以自己声明的其他任何东西。Lambda
只是() -> {}
特殊语法的名称,当将单方法接口作为参数传递时,可以提高可读性。它旨在替代此:
method(new Callback() {
@Override
public void call() {
// Classic interface implementation, lot of useless boilerplate code.
// method() is done, do whatever you want here.
}
});
所以在上面的例子中,Callback
是不是一个lambda,这只是一个普通的接口; lambda
是可用于实现它的快捷方式语法的名称。
对于使用谷歌搜索的任何人,最好使用java.util.function.BiConsumer
。例如:
Import java.util.function.Consumer
public Class Main {
public static void runLambda(BiConsumer<Integer, Integer> lambda) {
lambda.accept(102, 54)
}
public static void main(String[] args) {
runLambda((int1, int2) -> System.out.println(int1 + " + " + int2 + " = " + (int1 + int2)));
}
输出是:166
可以将Lambda表达式作为参数传递。要将Lambda表达式作为参数传递,参数的类型(接收lambda表达式作为参数)必须具有功能接口类型。
如果有功能界面-
interface IMyFunc {
boolean test(int num);
}
并且有一个过滤器方法仅在列表中大于5时才将int添加到列表中。请注意,此处的过滤器方法将函数接口IMyFunc作为参数之一。在这种情况下,可以将lambda表达式作为方法参数的参数传递。
public class LambdaDemo {
public static List<Integer> filter(IMyFunc testNum, List<Integer> listItems) {
List<Integer> result = new ArrayList<Integer>();
for(Integer item: listItems) {
if(testNum.test(item)) {
result.add(item);
}
}
return result;
}
public static void main(String[] args) {
List<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(4);
myList.add(6);
myList.add(7);
// calling filter method with a lambda expression
// as one of the param
Collection<Integer> values = filter(n -> n > 5, myList);
System.out.println("Filtered values " + values);
}
}
好吧,那很容易。lambda表达式的目的是实现功能接口。它是只有一种方法的接口。这是有关预定义和旧功能接口的出色文章。
无论如何,如果您想实现自己的功能接口,请创建它。仅举一个简单的例子:
public interface MyFunctionalInterface {
String makeIt(String s);
}
因此,让我们创建一个类,在其中创建一个方法,该方法接受MyFunctionalInterface的类型:
public class Main {
static void printIt(String s, MyFunctionalInterface f) {
System.out.println(f.makeIt(s));
}
public static void main(String[] args) {
}
}
您应该做的最后一件事是将MyFunctionalInterface的实现传递给我们定义的方法:
public class Main {
static void printIt(String s, MyFunctionalInterface f) {
System.out.println(f.makeIt(s));
}
public static void main(String[] args) {
printIt("Java", s -> s + " is Awesome");
}
}
而已!
Lambda不是对象,而是功能接口。使用@FuntionalInterface作为注释,可以定义尽可能多的功能接口。
@FuntionalInterface
public interface SumLambdaExpression {
public int do(int a, int b);
}
public class MyClass {
public static void main(String [] args) {
SumLambdaExpression s = (a,b)->a+b;
lambdaArgFunction(s);
}
public static void lambdaArgFunction(SumLambdaExpression s) {
System.out.println("Output : "+s.do(2,5));
}
}
输出如下
Output : 7
Lambda表达式的基本概念是定义您自己的逻辑,但已经定义了参数。因此,在上面的代码中,您可以将do函数的定义从添加定义更改为任何其他定义,但是您的参数限制为2。
C#处理此问题的大致方式(但表示为Java代码)。这样的事情几乎可以满足您的所有需求:
import static org.util.function.Functions.*;
public class Test {
public static void main(String[] args)
{
Test.invoke((a, b) -> a + b);
}
public static void invoke(Func2<Integer, Integer, Integer> func)
{
System.out.println(func.apply(5, 6));
}
}
package org.util.function;
public interface Functions {
//Actions:
public interface Action {
public void apply();
}
public interface Action1<T1> {
public void apply(T1 arg1);
}
public interface Action2<T1, T2> {
public void apply(T1 arg1, T2 arg2);
}
public interface Action3<T1, T2, T3> {
public void apply(T1 arg1, T2 arg2, T3 arg3);
}
public interface Action4<T1, T2, T3, T4> {
public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
}
public interface Action5<T1, T2, T3, T4, T5> {
public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
}
public interface Action6<T1, T2, T3, T4, T5, T6> {
public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
}
public interface Action7<T1, T2, T3, T4, T5, T6, T7> {
public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
}
public interface Action8<T1, T2, T3, T4, T5, T6, T7, T8> {
public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
}
//Functions:
public interface Func<TResult> {
public TResult apply();
}
public interface Func1<T1, TResult> {
public TResult apply(T1 arg1);
}
public interface Func2<T1, T2, TResult> {
public TResult apply(T1 arg1, T2 arg2);
}
public interface Func3<T1, T2, T3, TResult> {
public TResult apply(T1 arg1, T2 arg2, T3 arg3);
}
public interface Func4<T1, T2, T3, T4, TResult> {
public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
}
public interface Func5<T1, T2, T3, T4, T5, TResult> {
public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
}
public interface Func6<T1, T2, T3, T4, T5, T6, TResult> {
public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
}
public interface Func7<T1, T2, T3, T4, T5, T6, T7, TResult> {
public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
}
public interface Func8<T1, T2, T3, T4, T5, T6, T7, T8, TResult> {
public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
}
}
使用lambda作为参数具有灵活性。它启用Java中的函数式编程。基本语法是
参数-> method_body
以下是一种方法,您可以定义一个以功能接口(使用lambda)作为参数的方法。一个。如果您想定义在函数接口内部声明的方法,例如,函数接口作为从以下位置调用的方法的参数/参数给出main()
@FunctionalInterface
interface FInterface{
int callMeLambda(String temp);
}
class ConcreteClass{
void funcUsesAnonymousOrLambda(FInterface fi){
System.out.println("===Executing method arg instantiated with Lambda==="));
}
public static void main(){
// calls a method having FInterface as an argument.
funcUsesAnonymousOrLambda(new FInterface() {
int callMeLambda(String temp){ //define callMeLambda(){} here..
return 0;
}
}
}
/***********Can be replaced by Lambda below*********/
funcUsesAnonymousOrLambda( (x) -> {
return 0; //(1)
}
}
FInterface fi =(x)-> {return 0; };
funcUsesAnonymousOrLambda(fi);
可以在上面看到如何用接口替换lambda表达式。
上面解释了lambda表达式的一种特殊用法,还有更多。ref lambda中的Java 8 lambda无法修改外部lambda中的变量