EqualsIgnoreCase 的过滤谓词

Filter Predicate for EqualsIngnoreCase

我正在尝试为 Object is NotNull 和 EqualsIgnoreCase 编写一个过滤器谓词,但我无法为 EqualsIgnorecase 部分创建谓词。能给我点建议吗

我的代码是:

 basicDetailentity.forEach(prj -> {
      CharlieAddress billToAddress = addressList.stream()
          .filter(add -> Objects.nonNull(add.getSiteDuns())
              && add.getSiteDuns().equalsIgnoreCase(prj.getBillToDuns())
              && Objects.nonNull(add.getOrgName())
              && add.getOrgName().equalsIgnoreCase(prj.getOperatingUnit()))
          .findFirst().orElse(null);

我已经为 nonNull 部分创建了 2 个谓词,但发现很难为 equalsIgnoreCase 部分创建一个谓词,任何建议都会有所帮助

  public static final Predicate<CharlieAddress> CHARLIE_ADDRESS_DUNS_PRESENT =
      add -> Objects.nonNull(add.getSiteDuns());

  public static final Predicate<CharlieAddress> CHARLIE_ADDRESS_ORG_PRESENT =
      add -> Objects.nonNull(add.getOrgName());

问题是您的条件依赖于两个参数。您需要 地址 并且您需要 prj (项目?——此答案的其余部分假设如此)。

add.getSiteDuns().equalsIgnoreCase(prj.getBillToDuns())
 ^                                  ^

一个谓词接受一个单个参数和returns一个布尔值,所以除非你有一个充当闭包的lambda,它从封闭范围捕获一些变量(如果你希望谓词是一个静态字段,你可能不要)那么你所要求的是不可能的

final Project prj = /*something*/; // must be final or "effectively final"
Predicate<CharlieAddress> foo =
    add -> add.getSiteDuns().equalsIgnoreCase(prj.getBillToDuns());
                                            // ^ captured

还有另一个接口,BiPredicate 有两个参数。也许这就是您要找的。

BiPredicate<CharlieAddress, Project> foo =
    (add, prj) -> add.getSiteDuns().equalsIgnoreCase(prj.getBillToDuns());

你没有问,但你现有的谓词可以用 != null

来简化
public static final Predicate<CharlieAddress> CHARLIE_ADDRESS_DUNS_PRESENT =
    add -> add.getSiteDuns() != null;

public static final Predicate<CharlieAddress> CHARLIE_ADDRESS_ORG_PRESENT =
    add -> add.getOrgName() != null;

如果我可以假设 addressList 中的对象永远不会为 prj.getBillToDuns()prj.getBillToDuns() 设置空值,您的代码可以从

简化
basicDetailentity.forEach(prj -> {
  CharlieAddress billToAddress = addressList.stream()
      .filter(add -> Objects.nonNull(add.getSiteDuns())
          && add.getSiteDuns().equalsIgnoreCase(prj.getBillToDuns())
          && Objects.nonNull(add.getOrgName())
          && add.getOrgName().equalsIgnoreCase(prj.getOperatingUnit()))
      .findFirst().orElse(null);

basicDetailentity.forEach(prj -> {
  CharlieAddress billToAddress = addressList.stream()
      .filter(add -> prj.getBillToDuns().equalsIgnoreCase(add.getSiteDuns())
          && prj.getOperatingUnit().equalsIgnoreCase(add.getOrgName()))
      .findFirst().orElse(null);

或者如果你被允许使用 StringUtils from Apache Common Collections 那么它可以简单地是

basicDetailentity.forEach(prj -> { 
  CharlieAddress billToAddress = addressList.stream()
  .filter(add -> StringUtils.equalsIgnoreCase(add.getSiteDuns(), prj.getBillToDuns())
      && StringUtils.equalsIgnoreCase(add.getOrgName(), prj.getOperatingUnit()))
  .findFirst().orElse(null);

如果您仍然只想自己做,请创建一个实用方法,它将两个字符串作为参数并且 returns 如果它们都不为 null 并且相等且忽略大小写,则为 true。然后将其用作过滤器中的谓词

private boolean myEqualsIgnoreCase(String oneStr, String twoStr) {
    return oneStr != null && twoStr != null && oneStr.equalsIgnoreCase(twoStr);
}

basicDetailentity.forEach(prj -> { 
  CharlieAddress billToAddress = addressList.stream()
  .filter(add -> myEqualsIgnoreCase(add.getSiteDuns(), prj.getBillToDuns())
      && myEqualsIgnoreCase(add.getOrgName(), prj.getOperatingUnit()))
  .findFirst().orElse(null);

备注

除了上面的解释,我相信这段代码对于大型集合来说效率不是很高,如果我是你,我会为addressList实现某种基于Key-Value的搜索逻辑,这样我就可以提供一个包含 SiteDunesOrgName 的键然后映射(键值)将返回相应的地址对象作为值。