[玩转Java] Predicate的妙用

ℹ️ 在Java中,Predicate接口是一个函数式接口,它被用来表示一个接受单个输入参数并返回布尔值结果的条件或谓词。Predicate接口的常见用途主要集中在流操作和集合处理上,但它的应用场景非常广泛。以下是Predicate的几个妙用示例:

1. 使用Predicate进行流操作和过滤

Predicate最常见的用途是在Java Streams API中进行过滤操作。例如:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateExample {
    public static void main(String[] args) {
      
    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
    Predicate<String> startsWithA = name -> name.startsWith("A");
   
    List<String> result = names.stream().filter(startsWithA).collect(Collectors.toList());
    System.out.println(result); // 输出: [Alice]
}
  }

2. 组合Predicates

Predicate接口提供了三个默认方法:and, or, 和 negate,这些方法可以用来组合多个谓词。例如:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateExample {
    public static void main(String[] args) {
            List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
            Predicate<String> startsWithA = name -> name.startsWith("A");
            Predicate<String> lengthGreaterThanThree = name -> name.length() > 3;
            List<String> result = names.stream().filter(startsWithA.and(lengthGreaterThanThree)).collect(Collectors.toList());
            System.out.println(result); // 输出: [Alice]
        }
}

3. 用于集合的删除操作

Predicate也可以与集合的删除操作一起使用:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(Arrays.asList("Alice", "Bob", "Charlie", "David"));
    Predicate<String> startsWithA = name -> name.startsWith("A");
    
    names.removeIf(startsWithA);
    
    System.out.println(names); // 输出: [Bob, Charlie, David]
    }
}

4. 动态创建Predicates

可以根据条件动态创建Predicate,从而使代码更加灵活:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
    Predicate<String> dynamicPredicate = createPredicate("A", 3);

    List<String> result = names.stream().filter(dynamicPredicate).collect(Collectors.toList());
    System.out.println(result); // 输出: [Alice]
}

public static Predicate<String> createPredicate(String prefix, int minLength) {
    return name -> name.startsWith(prefix) && name.length() > minLength;
    }
}

5. 参数化行为

通过将Predicate作为方法参数传递,可以参数化方法行为:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
      List<String> filteredNames = filterNames(names, name -> name.contains("o"));

    System.out.println(filteredNames); // 输出: [Bob]
}

public static List<String> filterNames(List<String> names, Predicate<String> condition) {
    return names.stream()
                .filter(condition)
                .collect(Collectors.toList());
  }
}

6. 条件检查

Predicate可以用作条件检查,在代码中清晰地表达逻辑:

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
   Predicate<Integer> isEven = number -> number % 2 == 0;
   System.out.println(checkCondition(4, isEven)); // 输出: true
    System.out.println(checkCondition(7, isEven)); // 输出: false
}

public static boolean checkCondition(Integer number, Predicate<Integer> condition) {
    return condition.test(number);
  }
}

⭐️ 案例

平常我们比赛猜测谁是第一名那么怎么使用Java中的断言Predicate匹配中奖的?

/**
 * 构建竞猜断言
 *
 * @param leagueDependency
 * @return
 */
public static Predicate<SportPredictChampionResult> buildChampionPredicate(LeagueDependency leagueDependency) {
    List<Integer> championQuizType = leagueDependency.getChampionQuizType();
    BizLogUtils.sportInfo("竞猜配置类型leagueDependency", championQuizType);
    Predicate<SportPredictChampionResult> firstPred = (r) -> {
        boolean firstTeamPred = r.getFirstTeamId().equals(leagueDependency.getFirstTeamId());
        BizLogUtils.sportInfo("玩家", r.getPlayerId(), "猜第一名计算 firstTeamId", r.getFirstTeamId(), "期望FirstTeamId", leagueDependency.getFirstTeamId(), "第一名明细数据", r);
        return firstTeamPred;
    };
    Predicate<SportPredictChampionResult> secondPred = (r) -> {
        boolean secondTeamPred = r.getSecondTeamId().equals(leagueDependency.getSecondTeamId());
        BizLogUtils.sportInfo("玩家", r.getPlayerId(), "猜第二名计算 secondTeamId", r.getSecondTeamId(), "期望SecondTeamId", leagueDependency.getSecondTeamId(), "第二名明细数据", r);
        return secondTeamPred;
    };
    Predicate<SportPredictChampionResult> thirdPred = (r) -> {
        boolean thirdTeamPred = r.getThirdTeamId().equals(leagueDependency.getThirdTeamId());
        BizLogUtils.sportInfo("玩家", r.getPlayerId(), "猜第三名计算 thirdTeamId", r.getThirdTeamId(), "期望ThirdTeamId", leagueDependency.getThirdTeamId(), "第三名明细数据", r);
        return thirdTeamPred;
    };
    Predicate<SportPredictChampionResult> scorePred = (r) -> {
        boolean firstSecondScorePred = r.getFirstScore().equals(leagueDependency.getFirstScore()) && r.getSecondScore().equals(leagueDependency.getSecondScore());
        BizLogUtils.sportInfo("玩家", r.getPlayerId(), "猜比分计算 firstScore", r.getFirstScore(), "secondScore", r.getSecondScore(), "期望FirstScore", leagueDependency.getFirstScore(), "期望SecondScore", leagueDependency.getSecondScore(), "比分明细数据", r);
        return firstSecondScorePred;
    };

    Map<Integer, Predicate<SportPredictChampionResult>> predMap = ImmutableMap.of(
            SportLeagueChampionQuizEnum.CHAMPION.getValue(), firstPred,
            SportLeagueChampionQuizEnum.SECOND.getValue(), secondPred,
            SportLeagueChampionQuizEnum.THIRD.getValue(), thirdPred,
            SportLeagueChampionQuizEnum.SCORE.getValue(), scorePred
    );
    Predicate<SportPredictChampionResult> alwaysTrue = (r) -> true;
        // 将查询出来当前配置的的启用,一二三名还是比分,添加到匹配条件中 (如果配置里面有包含 冠军和亚军勾选项目,下面就会自动匹配到指定类型校验校验)
        // 比如 配置了一二名,championQuizType里面元素就会有[1,2], 那么组合成的断言条件就是:
        // true && xxx.getFirstTeamId().equals(leagueDependencyReq.getFirstTeamId()) &&  xxx.getSecondTeamId().equals(leagueDependencyReq.getSecondTeamId())
        for (Integer i : championQuizType) {
            BizLogUtils.sportInfo("结果配置类型,生成Predicate", predMap.get(i), "类型", i, "name", SportLeagueChampionQuizEnum.getByValue(i));
            alwaysTrue = alwaysTrue.and(predMap.get(i));
        }

    return alwaysTrue;
}
public enum SportLeagueChampionQuizEnum {
    CHAMPION(1, "第一名"),
    SECOND(2, "第二名"),
    THIRD(3, "第三名"),
    SCORE(4, "比分")
    ;
    private final Integer value;
    private final String name;
    // 省略枚举出参....
}
    /**
     * 将查询的条目,根据断言判断出状态值,并且记录到条目中
     * @param leagueDependencyReq
     * @param recordChampionList
     */
    public void loadChampionStatus(LeagueDependency leagueDependencyReq, List<SportPredictChampionResult> recordChampionList) {
        if (CollectionUtil.isEmpty(recordChampionList)) { log.info("记录为空,无需计算猜测结果"); return; }
        LocalDateTime openTime = LocalDateTime.now();

        Predicate<SportPredictChampionResult> championQuizPredicate = buildChampionPredicate(leagueDependencyReq);
        //使用断言判断出符合条件的记录条目状态值 并且装载到记录条目中。
        recordChampionList.stream().forEach(champion -> {
            if (championQuizPredicate.test(champion)) {
                champion.setStatus(SportQuizStatusEnum.READY_RECEIVE.getValue());
                champion.setCorrectFlag(true);
            } else {
                champion.setStatus(SportQuizStatusEnum.NOT_WIN.getValue());
                champion.setCorrectFlag(false);
            }
            champion.setOpenTime(openTime);
            log.info("计算猜测结果{}",champion);
        });
    }

🖍️ 总结

Predicate接口在Java中有广泛的应用,可以用于流操作、条件检查、动态创建条件、参数化方法行为等场景。它使代码更加灵活、简洁和可读,提高了代码的可维护性和重用性。在实际业务开发中,善用Predicate可以大大简化复杂逻辑的表达。

📚 参考资料 & 致谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OxYGC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值