[英]Using Java Lambdas like C++-style function pointers?
我对lambdas和Java8一般都是新手,所以如果这是一个简单的问题我会道歉。
我目前有一个课程,我希望在最后一个复杂的匹配上做一些getter:
public final class Foo {
public String getName();
public Type getType();
public List<Bar> getBarList();
....
}
我写了一个小辅助类来匹配:
public class MatchParameter<T> {
boolean expectMatch = true;
T valueToCheck;
public MatchParameter(T value, boolean shouldMatch) {
this.expectMatch = shouldMatch;
this.valueToCheck = value;
}
public boolean matches(Predicate<T> matcher) {
return matcher.test(valueToCheck) == expectMatch;
}
}
然后我有一个创建各种MatchParameters
的地方,比如检查名称,或者检查List<Bar>
包含特定的Bar
:
MatchParameter<String> nameParam = new MatchParameter(inputName, shouldMatch);
MatchParameter<Bar> barParam = new MatchParameter(inputBar, shouldMatch);
....
我目前卡住了记住每个MatchParameter
正在寻找的东西。 最终我的支票代码如下:
if(nameParam.matches(name -> currentFoo.getName().matches(name)) {
...
}
if(barParam.matches(bar -> currentFoo.getBarList().contains(bar)) {
...
}
...
在每种情况下,我传递的谓词是一个lambda,它有一些currentFoo.<accessorFns>
迭代currentFoo.<accessorFns>
最终取一个类型T,并返回一个布尔值。 我真正想做的是将访问器的逻辑移动到MatchParameter的创建。
有没有办法可以指定一个我可以在构造时传入的函数指针? 我希望它是某种可运行的(Foo,T)
。
在C ++中,我添加了一个本地函数指针,它将两个输入( Foo
和T
)带到MatchParameter的局部变量:
bool (*checkFn)(Foo f, T input);
然后我可以为每个实例化创建一个匿名函数,并更新我的MatchParameter matches
实现为:
public boolean matches(Foo f) {
return checkFn(f, valueToCheck) == expectMatch;
}
我的实例化是:
MatchParameter<String> nameParam = new MatchParameter<>(
inputName,
shouldMatch,
(Foo f, String input) -> boolean { return f.getName().matches(input); }
);
是否有相同的方法在Java中实现这一点?
如果你的函数应该总是返回一个布尔值,那么你可以将BiPredicate
传递给构造函数:
public class MatchParameter<T> {
boolean expectMatch = true;
T valueToCheck;
BiPredicate<Foo, T> predicate;
public MatchParameter(T value, boolean shouldMatch, BiPredicate<Foo, T> function) {
this.expectMatch = shouldMatch;
this.valueToCheck = value;
this.predicate = predicate;
}
public boolean matches(Predicate<T> matcher) {
return matcher.test(valueToCheck) == expectMatch;
}
}
然后,您可以按如下方式实例化对象:
MatchParameter<String> nameParam = new MatchParameter<>(inputName, shouldMatch,
(foo, input) -> f.getName().matches(input)
);
最后,您可以创建一个函数来测试BiPredicate
到Foo
对象:
public boolean matches(Foo f) {
return predicate.test(f, valueToCheck) == expectMatch;
}
我认为MatchParameter
类是没有意义的,因为不需要封装给定的输入值和条件。 相反,我只想创造一个Predicate<Foo>
基于以上的一些财产状况Foo
,需要匹配一个给定的输入值。 这可以通过静态方法实现,该方法接收:
Function<Foo, U>
BiPredicate<U, V>
接收提取的属性(类型U
)和输入值(类型V
)以检查 这个静态方法的返回值是Predicate<Foo>
。 这是代码:
public static <T, U, V> Predicate<T> matchesFor(
Function<T, U> extractor,
BiPredicate<U, V> condition,
V inputValue,
boolean shouldMatch) {
return t -> condition.test(extractor.apply(t), inputValue) == shouldMatch;
}
// A handy overload
public static <T, U, V> Predicate<T> matchesFor(
Function<T, U> extractor,
BiPredicate<U, V> condition,
V inputValue) {
return matchesFor(extractor, condition, inputValue, true);
}
然后,无论您在何处创建匹配器,请使用matchesFor
方法:
Predicate<Foo> nameMatcher = matchesFor(
Foo::getName, // if Foo's name
String::matches, // matches
SOME_REGEX); // this specific input regex
Predicate<Foo> barsMatcher = matchesFor(
Foo::getBarList, // if Foo's Bar list
List::contains, // contains
SOME_BAR); // this specific input Bar
最后,在循环中,只需使用上面创建的谓词:
if (nameMatcher.test(currentFoo)) {
// ...
}
if (barsMatcher.test(currentFoo)) {
// ...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.