Java Lambda表达式的其他参数 - 如何?

时间:2017-09-14 09:27:02

标签: java lambda

如何在命名的Java Lambda Expressions中使用其他变量,就像我可以用匿名变量一样?我找到了一个解决方法(方法返回一个Lambda),但出于好奇:这是否也可以用纯Lambda语法表达?我在常用的教程和参考资料中找不到答案。

请考虑以下示例代码:

Arrays.asList(1,2,3,4,5).stream().filter( i -> i<3 ).toArray();

我可以给这个匿名的Lambda命名:

Arrays.asList(1,2,3,4,5).stream().filter(LessThanThree).toArray();
[...]
Predicate<Integer> LessThanThree = i -> i<3;

但是如果我想使用变量而不是常量,则相同的语法将不起作用。因为我找不到一种方法来声明名为Lambda的参数:

编辑:谢谢你,dpr,暗示这是一个范围问题!我增强了以下代码块,试图澄清我感兴趣的内容。

filterIt(3);
[...]
void filterIt(int x) {
    Arrays.asList(1,2,3,4,5).stream().filter(LessThanX).toArray();
}
[...]
Predicate<Integer> LessThanX = i -> i<x; // won't compile!

解决方法似乎是一个返回Lambda的方法:

private Predicate<Integer> lessThanX(int x) {
    return i -> i<x;
}

但是:有没有办法用纯名为Lambda的方法来制定它?

5 个答案:

答案 0 :(得分:4)

在您的情况下,您可以使用BiPredicate<Integer, Integer> lessThan = (i, j) -> i < j; Arrays.asList(1,2,3,4,5).stream().filter(i -> lessThan.test(i, 3)).collect(Collectors.toList()); 代替正常谓词

@FunctionalInterface

如果您需要使用2个以上输入的测试,则可能需要编写自己的POSTGRESQL_USER POSTGRESQL_PASSWORD POSTGRESQL_DATABASE 作为lambda。

答案 1 :(得分:1)

如果添加第二个变量(例如示例中的x),则不再有Predicate<Integer>。你有一个BiFunction<Integer,Integer,Boolean>(即一个带有两个参数的函数,返回一个Boolean)。

您可以定义lambda表达式并将其指定给BiFunction<Integer,Integer,Boolean>

BiFunction<Integer,Integer,Boolean> LessThanX = (i,x) -> i<x;

为了将其转换为Predicate<Integer>,您需要第二个依赖于第一个的lambda表达式:

Predicate<Integer> LessThan3 = i -> LessThanX.apply (i, 3);

当然,您可以直接使用BiFunction

Arrays.asList(1,2,3,4,5).stream().filter(i -> LessThanX.apply (i, 3)).toArray();

答案 2 :(得分:1)

请注意,此lambda:a -> a < b只接受一个参数 - ax的值被烘焙到函数中。

在循环中使用它时:

for(int b = 0; b<20; b++) {
   IntStream.range(15,25)
        .filter( a -> a < b)
        ...;
}

您每次围绕b循环创建新谓词:

  a -> a < 0
  a -> a < 1
  a -> a < 2

......等等。在此示例中,如果b不是有效的最终,编译器将禁止它。

您可以通过定义本地Predicate

来完成同样的事情
for(int b = 0; b<20; b++) {
   Predicate<Integer> lessThanB = a -> a < b;
   IntStream.range(15,25)
        .filter(lessThanB)
        ...;
}

但是你不能在b是最终变量的范围之外定义lessThanB。

您可以定义BiPredicate

BiPredicate<Integer,Integer> lessThan = (a,b) -> a < b;

...但您无法在BiPredicate处使用Predicate - 例如在Stream.filter() Currying BiPredicate变为Predicate,其中一个参数被烘焙:

final int x = 5;
Predicate<Integer> lessThanX = n -> lessThan.test(n,x);

...您可以在filter()

中内联这样做
.filter( n -> lessThan.test(n,x))

但是,您获得的收益并不高 - 您仍在为Predicate的每个新值创建新的x

没有TriPredicate但FP的原则是 n 单参数函数链相当于一个 n -param函数。您不需要多个参数(BiPredicate是礼貌的)

即代替:

TriFunction<String, String, String, User> finder = (company, dept, name) -> { ...}`

......你有:

Function<String, Function<String, Function<String, User>>> format =
      company -> dept -> name -> 
          String.format("Company: %s\nDept: %s\nName: %s", company, dept, name);

被称为String s = format.apply("Daimler").apply("Accounts").apply("John Doe")

...或者更不常见的是,三个参数Predicate将是:

Function<String, Function<String, Predicate<String>>> userExists = 
    company -> dept -> name ->  somethingThatReturnsBoolean(company, dept, name);

......被称为:

boolean exists = 
    userExists.apply("Daimler").apply("Accounts").test("John Doe")

答案 3 :(得分:0)

此代码编译!

int x = 3;
Predicate<Integer> LessThanThree = i -> i<x;
Arrays.asList(1,2,3,4,5).stream().filter(LessThanThree).toArray();

请记住,x必须是effectively final! 只要你添加另一行x = 4就会中断。

答案 4 :(得分:0)

您的代码段已经完美无缺。

data

我更喜欢它是方法而不是变量coz,该方法赋予操作或比较更多的意义。对于这种检查大小而不是影响的小案例,当然是一个真实案例场景,方法更好,它还允许您在 List<Integer> vals = Arrays.asList(1,2,3,4,5); int compare_int = 2; //Add this compare_int = 4;//Variable used in lambda expression should be final or effectively final Predicate<Integer> GT_3 = integer -> integer > compare_int; System.out.println(vals.stream().filter(GT_3).count());//prints 3 方法中共享。