繁体   English   中英

使用Java Lambdas就像C ++一样 - 函数指针?

[英]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 ++中,我添加了一个本地函数指针,它将两个输入( FooT )带到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)
);

最后,您可以创建一个函数来测试BiPredicateFoo对象:

public boolean matches(Foo f) {
    return predicate.test(f, valueToCheck) == expectMatch;
}

我认为MatchParameter类是没有意义的,因为不需要封装给定的输入值和条件。 相反,我只想创造一个Predicate<Foo>基于以上的一些财产状况Foo ,需要匹配一个给定的输入值。 这可以通过静态方法实现,该方法接收:

这个静态方法的返回值是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM