“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); 没有区别为什么方法参考不起作用?
您可以创建自己的谓词:
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);
在这种情况下你不能用方法引用来表达它。如果您想使用迭代的当前元素作为另一个函数的参数,它会起作用。看看下面的例子:
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)
表达完全不同的表达式,不能用单个方法引用来表示。我希望它有帮助。
String
contains
方法需要一个参数,在本例中为“o”。
当我们通常指定谓词时过滤字符串列表 sytax 是 a -> a.contains("o").
IntelliJ 仅当方法没有参数时才给出建议。
例如当您指定这样的谓词时:
a -> a.isEmpty()
替代语法是
String::isEmpty
,它比前一种更具可读性。
但是,如果您需要使用一个或多个参数调用方法的谓词,您没有其他方法可以指定除此之外的其他方法:
a -> a.contains
静态可重用谓词
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());
}
您可以在测试类中添加一个返回谓词的方法
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);
}
..
}
我推荐使用
listTemp.stream().filter('o'::contains)
然后根据需要终止此流。