方法引用在 Java 流过滤器中不起作用

Method references not working in Java stream filter

我有一个包含一些字符串的列表,我想过滤这些列表,但是方法引用 ::startsWith 没有像我预期的那样工作。

private static final String KEY = "key=";

List<String> keyList = List.of("key=123", "value12", "value=34", "key=5678");

List<String> filtered = keyList.stream().filter(KEY::startsWith).collect(Collectors.toList());
List<String> filtered1 = keyList.stream().filter(e -> e.startsWith(KEY)).collect(Collectors.toList());
List<String> filtered2 = keyList.stream().filter("key="::startsWith).collect(Collectors.toList());

只有 filtered1 有预期的两个条目,其他列表为空。为什么 KEY::startsWith 没有按预期工作?

你做错了。

.filter(KEY::startsWith)

的含义相同
.filter(k->KEY.startsWith(k))

这会检查 KEY 是否以要过滤的元素开头。

但您想检查要过滤的元素是否以键开头。

.filter(k->k.startsWith(KEY))

如果你查看 the Java Language Specification, chapter 15.13,你可以看到:

The target reference of an instance method (§15.12.4.1) may be provided by the method reference expression using an ExpressionName, a Primary, or super, or it may be provided later when the method is invoked. The immediately enclosing instance of a new inner class instance (§15.9.2) is provided by a lexically enclosing instance of this (§8.1.3).

这意味着它将使用::运算符左侧的变量作为对象来调用startsWith

这在the method references page of the Java Tutorials中也有解释:

Reference to an Instance Method of an Arbitrary Object of a Particular Type The following is an example of a reference to an instance method of an arbitrary object of a particular type:

String[] stringArray = { "Barbara", "James", "Mary", "John",
    "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);

The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b).

KEY::startsWith 表示:

x -> KEY.startsWith(x)

所以您正在检查 key= 是否以 key=123 等开头,这是错误的方法。您应该检查 key=123 是否以 key= 开头。 "key="::startsWith.

也是如此

您不能真正在此处使用对 startsWith 的方法引用。 如果 String 中有一个名为 isStartOf 的方法:

public boolean isStartOf(String other) {
    return other.startsWith(this);
}

那么你可以使用 KEY::isStartOf,但我认为没有内置的方法。