MyClass.method((a, b) -> a+b);
class MyClass{
//How do I define this method?
static int method(Lambda l){
return l(5, 10);
}
}
MyClass.method((a, b) -> a+b);
class MyClass{
//How do I define this method?
static int method(Lambda l){
return l(5, 10);
}
}
Lambda表达式仅是一个调用现场的构造: 接收Lambda表达式的对象不需要知道Lambda表达式的存在,而是接受一个具有相应方法的接口。
换句话说,您定义或使用一个函数接口(即只有一个方法的接口),该接口接受并返回您想要的内容。
自Java 8以来,在 java.util.function
中有一组常用的接口类型。
对于这个特定的用例,有一个 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);
}
然后使用lambda表达式作为参数调用该方法:
public static void main(String[] args) {
TwoArgIntOperator addTwoInts = (a, b) -> a + b;
int result = method(addTwoInts);
System.out.println("Result: " + result);
}
使用自己的接口有一个优点,那就是你可以使用更加明确表示意图的名称。
(int a, int b, int c)
传递给TwoArgIntOperator
会发生什么?如果TwoArgIntOperator
有两个具有相同签名的方法会发生什么?这个答案很令人困惑。 - Tomáš ZatoRunnable
或 Producer<T>
(取决于是否需要返回值)作为你的函数式接口。 - Paŭlo Ebermann要使用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
文档的链接已失效。 - Hendrikto对于没有超过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 已经提供的所有接口。回调函数
接口: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
是您可以使用的快捷语法来实现它的名称。
有一个公共的Web可访问版本的Lambda-enabled Java 8 JavaDocs,链接在http://lambdafaq.org/lambda-resources上。(这显然应该是对Joachim Sauer答案的评论,但我无法通过我的SO帐户获得所需的声誉点数来添加评论。) lambdafaq网站(我维护它)回答了这个问题和许多其他Java-lambda问题。
NB: 这个答案是在Java 8 GA文档变为公开可用之前写的。我保留了这个答案,因为Lambda FAQ 对于学习Java 8中引入的功能仍然可能有用。
interface IMyFunc {
boolean test(int num);
}
还有一个筛选方法,只有在列表中的整数大于5时才添加。请注意,筛选方法具有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);
}
}
如果您正在搜索此问题,一个好的解决方法是使用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)));
}
Function<Integer, Integer> f1 = num->(num*2+1);
System.out.println(f1.apply(10));
Predicate<Integer> f2= num->(num > 10);
System.out.println(f2.test(10));
System.out.println(f2.test(11));
Supplier<Integer> f3= ()-> 100;
System.out.println(f3.get());
@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表达式作为参数传递,我们需要一个可以容纳它的类型。就像我们在原始的int或Integer类中保存整数值一样。Java没有单独的类型用于Lambda表达式,而是使用接口作为类型来保存参数。但这个接口应该是一个函数式接口。