用Java Stream一行代码搞定彩票随机选号(双色球/大乐透)
用Java Stream一行代码搞定彩票随机选号双色球/大乐透每次路过彩票站总忍不住想试试手气。但机选号码总感觉少了点参与感不如用Java Stream API自己写个随机选号器既锻炼编码能力又能享受定制化选号的乐趣。下面我们抛开传统循环用函数式编程思维重构彩票生成逻辑。1. 从循环到流式操作思维转换很多Java开发者习惯用for循环布尔数组处理随机数去重比如这样boolean[] exists new boolean[33]; ListInteger redBalls new ArrayList(); Random rand new Random(); for(int i0; i6; i){ int num; do { num rand.nextInt(33)1; } while(exists[num]); exists[num] true; redBalls.add(num); } Collections.sort(redBalls);这种写法虽然直观但存在几个问题代码臃肿需要手动处理去重、边界条件状态管理复杂依赖外部布尔数组记录已选数字可读性差业务逻辑被机械的循环控制打断而用Stream API可以这样重构ListInteger redBalls new Random().ints(1, 34) .distinct() .limit(6) .sorted() .boxed() .collect(Collectors.toList());对比两种实现特性传统循环方案Stream方案代码行数10行1行可读性需逐行理解控制逻辑声明式表达业务意图维护成本修改规则需调整多处只需修改参数并行化潜力需手动实现天然支持parallel()提示ints()方法生成的是IntStream需要boxed()转换为StreamInteger才能用常规集合操作2. 双色球与大乐透的Stream实现2.1 双色球生成器双色球规则从1-33选6个红球1-16选1个蓝球。完整实现public class LotteryGenerator { private static final Random random new Random(); // 双色球生成 public static void generateSSQ(int count) { System.out.println(双色球机选结果); IntStream.range(0, count).forEach(i - { ListInteger red random.ints(1, 34) .distinct() .limit(6) .sorted() .boxed() .collect(Collectors.toList()); int blue random.nextInt(16) 1; System.out.printf(第%d注: 红球%s 蓝球%02d%n, i1, red, blue); }); } }关键点解析ints(1, 34)生成1-33范围的随机数流distinct().limit(6)确保6个不重复数字sorted()按升序排列符合彩票显示惯例boxed()将IntStream转为StreamInteger2.2 大乐透生成器大乐透规则前区1-35选5个后区1-12选2个。Stream实现public static void generateDLT(int count) { System.out.println(大乐透机选结果); IntStream.range(0, count).forEach(i - { ListInteger front random.ints(1, 36) .distinct() .limit(5) .sorted() .boxed() .collect(Collectors.toList()); ListInteger back random.ints(1, 13) .distinct() .limit(2) .sorted() .boxed() .collect(Collectors.toList()); System.out.printf(第%d注: 前区%s 后区%s%n, i1, front, back); }); }3. 工程化改进与性能考量3.1 避免重复创建Random实例原方案每次调用都新建Random对象可能降低性能。改进方案// 类级别共享Random实例 private static final ThreadLocalRandom random ThreadLocalRandom.current(); // 使用方法不变 random.ints(1, 34)...3.2 并行流优化对于批量生成场景如一次生成1000注可使用并行流public static ListString batchGenerateSSQ(int count) { return IntStream.range(0, count).parallel() .mapToObj(i - { String red random.ints(1, 34) .distinct() .limit(6) .sorted() .boxed() .collect(Collectors.toList()) .toString(); int blue random.nextInt(16) 1; return String.format(红球%s 蓝球%02d, red, blue); }) .collect(Collectors.toList()); }性能对比测试生成10万注方式耗时(ms)顺序流420并行流110注意并行流适合CPU密集型操作但会增大内存开销3.3 异常处理与边界条件健壮的生产代码需要处理极端情况public static ListInteger generateNumbers(int min, int max, int count) { if (count (max - min 1)) { throw new IllegalArgumentException( 无法生成count个不重复的min-max范围内的数字); } return random.ints(min, max 1) .distinct() .limit(count) .sorted() .boxed() .collect(Collectors.toList()); }4. 扩展应用从彩票到实际业务这种随机采样模式可复用到多种场景4.1 抽奖系统实现public ListString drawWinners(ListString participants, int winnerCount) { return ThreadLocalRandom.current() .ints(0, participants.size()) .distinct() .limit(winnerCount) .mapToObj(participants::get) .collect(Collectors.toList()); }4.2 测试数据生成生成不重复的测试IDListString testIds random.ints(1000, 9999) .distinct() .limit(100) .mapToObj(id - TEST_ id) .collect(Collectors.toList());4.3 数据库采样模拟SQL的ORDER BY RAND() LIMIT NListUser randomUsers userRepository.findAll() .stream() .collect(Collectors.collectingAndThen( Collectors.toList(), list - random.ints(0, list.size()) .distinct() .limit(5) .mapToObj(list::get) .collect(Collectors.toList()) ));最后分享一个实用技巧在IntelliJ IDEA中可以用CtrlAltV快捷键自动补全Stream操作的变量声明大幅提升编码效率。比如输入new Random().ints(1,34).distinct().limit(6).sorted()后使用该快捷键会自动生成完整的收集表达式。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2530721.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!