如何使用java 8方法参考表达“(String a)-> a.contains(“o”)”

问题描述 投票:0回答:6

“String::contains”是错误的。但如何表达 lambda 呢?

此外,当我在 IntelliJ IDEA 中编写此内容时:

obj.testPredicate(list, String::contains);

我在“String::contains”中收到错误:无法从静态上下文引用非静态方法。但 contains 不是静态方法。我对这些提示感到困惑。

我的代码如下:

public <T> List<T> testPredicate(List<T> list , Predicate<T> predicate){
    List<T> result = new ArrayList<>();
    for(T t: list){
        if(predicate.test(t)){
            result.add(t);
        }
    }
    return result;
}

这是来电者:

@Test
public void testPredicate() throws Exception {
    List<String> listTemp = lambda.testPredicate(list, s -> s.contains("o"));
    System.out.println(listTemp);
}

为什么最简单的lambda不能用方法引用代替?

我看到了 使用方法引用而不是多参数 lambda

它说

(2) 如果 func 是一个实例方法,那么 SomeClass::func 是一个使用第一个参数作为实例的 lambda,如您所想: (a, b, c) -> a.func(b, c);

与我的 (String a, String b)-> a.contains(b); 没有区别为什么方法参考不起作用?

java lambda java-8 method-reference
6个回答
3
投票

您可以创建自己的谓词:

public class StringPredicates {
  public static Predicate<String> contains(String contained) {
    return s -> s.contains(contained);
  }
}

然后你可以像这样使用它们:

obj.testPredicate(list, StringPredicates.contains("o"));

注意,您不需要方法引用来使用这样的构造。正如我常说的:需要时使用正确的工具!在这种情况下,您有一个变量,因此不建议使用方法引用。

如果你确实必须使用方法引用,你可以这样写:

public static boolean containsO(String s) {
  return s.contains("o");
}

然后使用它:

obj.testPredicate(list, StringPredicates::containsO);

1
投票

在这种情况下你不能用方法引用来表达它。如果您想使用迭代的当前元素作为另一个函数的参数,它会起作用。看看下面的例子:

final String str = "o";

final List<String> list = Arrays.asList("lorem", "ipsum", "dolor", "sit", "amet");
list.stream()
        .filter(it -> it.contains(str)) // (1)
        .filter(it -> str.contains(it)) // (2)
        .filter(str::contains)  // (3)
        .findFirst();

在这种情况下,

(2)
(3)
是相等的,并且
(1)
表达完全不同的表达式,不能用单个方法引用来表示。我希望它有帮助。


0
投票

String

contains
方法需要一个参数,在本例中为“o”。

当我们通常指定谓词时过滤字符串列表 sytax 是 a -> a.contains("o").

IntelliJ 仅当方法没有参数时才给出建议。

例如当您指定这样的谓词时:

a -> a.isEmpty()

替代语法是

String::isEmpty
,它比前一种更具可读性。

但是,如果您需要使用一个或多个参数调用方法的谓词,您没有其他方法可以指定除此之外的其他方法:

a -> a.contains


0
投票

静态可重用谓词

    public static Predicate<String> contains(String contained) {
        return s -> s.contains(contained);
    }

测试代码

@Test
    public <T> List<T> testPredicate(List<T> list , Predicate<T> contains){
    return list.stream()
        .filter(contains)
        .collect(Collectors.toList());
    }

0
投票

您可以在测试类中添加一个返回谓词的方法

public class Test
{
    ..
    public static Predicate<String> contains_o()
    {
        return s -> s.contains("o");
    }

然后在测试谓词时使用它

    @Test
    public void testPredicate() throws Exception
    {
        List<String> listTemp = lambda.testPredicate(list, Test.contains_o());
        System.out.println(listTemp);
    }
    ..
}

0
投票

我推荐使用

listTemp.stream().filter('o'::contains)

然后根据需要终止此流。

© www.soinside.com 2019 - 2024. All rights reserved.