【问题标题】:How to iterate a list of Predicates如何迭代谓词列表
【发布时间】:2020-05-24 02:10:30
【问题描述】:

我有一个 Spring Boot 应用程序,我们有一个 application.yml,上面有一组功能标志

featureFlag:
    featureOne:true
    featureTwo:true
    featureThree:true
    featureFour:false

然后这个文件被这个类读取

@Configuration
@ConfigurationProperties(prefix="featureFlag")
public class FeatureFlag{

private Boolean featureOne;
private Boolean featureTwo;
private Boolean featureThree;
private Boolean featureFour;
/*The predicates based on the feature flags*/

private Predicate<FeatureFlag> isFeatureFlagOneEnabled = featureFlag.isFeatureOne();
private Predicate<FeatureFlag> isFeatureFlagTwoEnabled = featureFlag.isFeatureTwo();
private Predicate<FeatureFlag> isFeatureFlagThreeEnabled = featureFlag.isFeatureThree();
private Predicate<FeatureFlag> isFeatureFlagFourEnabled = featureFlag.isFeatureFour();
}

我想传递实际的谓词并迭代它们中的每一个,但我想知道我是否可以做一个通用函数,我传递谓词列表及其要测试的值,如果它们都为真,则函数给我一个真否则假

然后在这个类中添加一些这样的代码,因为我想按需生成这个列表,例如我有一个购买 featureOne 和 featureTwo 的客户 x,在这个例子中我创建一个这样的列表

Set<Predicate<FeatureFlag>> rulesForClientX = new HashSet<>();
rulesForClientX.add(isFeatureFlagOneEnabled);
rulesForClientX.add(isFeatureFlagTwoEnabled);

然后我想为该客户端创建一个特定的逻辑并将之前创建的谓词列表传递给它,但我想我需要这样的东西

Function<List<Predicate<FeatureFlag>>, Boolean> iteratePredicates = (predicates) -> { 
    //test each predicate and return true if all of them are true otherwise return false
}

【问题讨论】:

  • "...如果所有这些都是真的..." - 这是什么意思?你给的两个Predicate是互斥的。
  • 好吧,在我的具体情况下,我有一个 featureFlags 列表,最后我们需要验证所有这些都已启用才能执行某些代码块,否则该代码块不应该被执行
  • 看起来没有完全适合的 Java API,你必须解决这个问题并构建一些额外的代码,不确定 Stream.takeWhile()Stream.dropWhile 是否可以提供帮助:docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/…
  • A Predicate 不是一个值,而是一个一元函数。它需要一些东西(在这个例子中很可能是一个Integer)作为输入并返回一个boolean。也许需要stream()ing 标志和reduce(...)ing 它们的组合。
  • 那么你应该用数据更新确切的场景,以便我们可以帮助你@jam

标签: java lambda java-8 functional-programming predicate


【解决方案1】:

您可以创建一个接受Set&lt;Predicate&lt;FeatureFlag&gt;&gt; 和值的方法,然后您可以流式传输一组谓词并使用allMatch

public boolean testPredicates(Set<Predicate<FeatureFlag>> predicates, Integer value) {
  return predicates.stream().allMatch(pre->pre.test(value));

 }

【讨论】:

  • 使用 pre.test(value) 将要求值的类型为 FeatureFlag
  • 实际上帖子中的代码对我来说并不是很清楚,我要求 OP 上传到 git 以便我可以查看@Naman,你说得对,它应该是 FeatureFlag
【解决方案2】:

Predicates

您应该期待的是链接您拥有的谓词。

我传递了谓词列表及其要测试的值,如果全部 其中为真函数返回真否则为假

根据您的要求,这应该是这样的;

public Predicate<FeatureFlag> chainPredicates(Set<Predicate<FeatureFlag>> predicates) {
    return predicates.stream()
                     .reduce(Predicate::and) // all true
                     .orElse(p -> false); // or false
}

消费Predicate

现在,您可以轻松地使用这个Predicate

boolean testFeatureFlag(Set<Predicate<FeatureFlag>> predicates, FeatureFlag value) {
    return chainPredicates(predicates).test(value);
}

或在集合上说 List&lt;FeatureFlag&gt; 以过滤掉特定的 FeatureFlags 为:

List<FeatureFlag> selectiveFeatures(Set<Predicate<FeatureFlag>> predicates, List<FeatureFlag> featureFlags) {
    Predicate<FeatureFlag> flagPredicate  = chainPredicates(predicates);
    return featureFlags.stream()
            .filter(flagPredicate)
            .collect(Collectors.toList());
}

【讨论】:

  • 是的,这正是我想要做的,我的意思是我想创建非常具体的函数,然后在较小的函数的基础上构造更大的函数,我会试试这个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多