AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79304318
Accepted
Basil Bourque
Basil Bourque
Asked: 2024-12-24 05:46:39 +0800 CST2024-12-24 05:46:39 +0800 CST 2024-12-24 05:46:39 +0800 CST

在 Java 中对随机 IntStream 进行过滤时没有结果

  • 772

我代表一组海龟,每只海龟都有孵化的时刻。我想随机选择任何一只成熟的海龟。

在这个水族馆模拟中,我假装几分钟就是几年。

record Turtle(
        String name ,
        Instant hatched ,
        Duration lifespan
)
{
    static final Duration MATURITY = Duration.ofMinutes ( 4 );

    Duration age ( ) { return Duration.between ( this.hatched , Instant.now ( ) ); }
}

我用来ThreadLocalRandom生成一个随机整数。我使用这些整数作为我的对象IntStream的索引。我检查那只海龟的年龄,看它是否超过了预定义的持续时间。如果没有成熟,就让流继续。ListTurtleMATURITY

当然,可能还没有海龟成熟。所以我将返回类型定义为Optional < Turtle >,如果没有找到海龟,则为空。

问题是我的流似乎失败了,没有返回任何结果。为什么?

public class Aquarium
{
    public static void main ( String[] args )
    {
        System.out.println ( "INFO Demo start. " + Instant.now ( ) );

        // Sample data.
        List < Turtle > turtles =
                List.of (
                        new Turtle ( "Alice" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 3 ) ) , Duration.ofMinutes ( 17 ) ) ,
                        new Turtle ( "Bob" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 2 ) ) , Duration.ofMinutes ( 16 ) ) ,
                        new Turtle ( "Carol" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 1 ) ) , Duration.ofMinutes ( 18 ) ) ,
                        new Turtle ( "Davis" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 2 ) ) , Duration.ofMinutes ( 22 ) )
                );
        System.out.println ( "turtles = " + turtles );

        // Logic
        Optional < Turtle > anArbitraryMatureTurtle =
                ThreadLocalRandom
                        .current ( )
                        .ints ( 0 , turtles.size ( ) )
                        .filter (
                                ( int randomIndex ) -> turtles.get ( randomIndex ).age ( ).compareTo ( Turtle.MATURITY ) > 0
                        )
                        .mapToObj ( turtles :: get )
                        .findAny ( );
        System.out.println ( "anArbitraryMatureTurtle = " + anArbitraryMatureTurtle );

        // Wrap-up
        try { Thread.sleep ( Duration.ofMinutes ( 30 ) ); } catch ( InterruptedException e ) { throw new RuntimeException ( e ); } // Let the aquarium run a while.
        System.out.println ( "INFO Demo end. " + Instant.now ( ) );
    }
}
java
  • 2 2 个回答
  • 68 Views

2 个回答

  • Voted
  1. Basil Bourque
    2024-12-24T05:46:39+08:002024-12-24T05:46:39+08:00

    InfiniteStream可以无限循环

    您无意中使无限陷入了无限循环IntStream。

    您IntStream创建的ThreadLocalRandom.ints是无限的,会在您定义的范围内不断生成一个又一个随机数。可能会出现重复,因为随机数会不断生成,直到您的流达到终止操作。

    您调用findAny终止流。但是查看您的示例数据。您的所有海龟都很年轻,没有一只海龟的年龄符合您的IntPredicate超过MATURITY持续时间的测试。因此,您的所有海龟都没有通过年龄测试。因此,findAny永远不会找到任何Turtle,因此它永远不会返回任何Optional < Turtle >。

    这意味着随机数生成不断进行,产生一个又一个索引号。对于每个随机数,我们访问List对象Turtle。但没有一个通过我们的谓词测试。因此,我们的流永不终止。这个随机生成器 -> List#get-> 谓词测试程序无休止地继续。在这个无限循环中,流永不终止,看起来什么都没有发生。实际上,发生了很多事情,一个非常繁忙的 CPU 核心生成数字、访问列表并计算和比较持续时间,无休止地进行。

    我们可以通过更改样本数据来证明这一点。启动Bob&Davis鱼,孵化日期为 7 分钟前,而不是 2 分钟前。再次运行代码,看看它们是否都是随机挑选的,而且挑选速度非常快。

            List < Turtle > turtles =
                    List.of (
                            new Turtle ( "Alice" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 3 ) ) , Duration.ofMinutes ( 17 ) ) ,
                            new Turtle ( "Bob" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 7 ) ) , Duration.ofMinutes ( 16 ) ) ,
                            new Turtle ( "Carol" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 1 ) ) , Duration.ofMinutes ( 18 ) ) ,
                            new Turtle ( "Davis" , Instant.now ( ).truncatedTo ( ChronoUnit.MINUTES ).minus ( Duration.ofMinutes ( 7 ) ) , Duration.ofMinutes ( 22 ) )
                    );
    

    anArbitraryMatureTurtle = 可选[Turtle[name=Davis,孵化时间=2024-12-23T21:17:00Z,寿命=PT22M]]

    解决方案

    没有解决方案可以直接修复当前代码†。如果没有保证终止,则不能使用无限流。

    相反,您必须重写代码。

    一种重写可能是复制您的List对象Turtle。对它们进行打乱,将列表按随机顺序排列。然后流式传输该随机列表,直到找到一个满足谓词测试条件的列表。如果没有满足这些条件的列表,则在详尽检查每个元素后流式传输结束,并Optional返回空值。

    将您的逻辑部分更改为:

            // Logic
            List < Turtle > turtlesShuffled = new ArrayList <> ( turtles );
            Collections.shuffle ( turtlesShuffled );
            Optional < Turtle > anArbitraryMatureTurtle =
                    turtlesShuffled
                            .stream ( )
                            .filter (
                                    turtle -> turtle.age ( ).compareTo ( Turtle.MATURITY ) > 0
                            )
                            .findAny ( );
    

    不再有随机索引。

    当与所有未成熟的幼龟一起运行时:

    anArbitraryMatureTurtle = Optional.empty

    相同的逻辑可以用常规for循环而不是来实现Stream。我发​​现在Stream这个特定情况下语法更具表现力。

            // Logic
            List < Turtle > turtlesShuffled = new ArrayList <> ( turtles );
            Collections.shuffle ( turtlesShuffled );
            Optional < Turtle > anArbitraryMatureTurtle = Optional.empty ( );
            for ( Turtle turtle : turtlesShuffled )
            {
                if ( turtle.age ( ).compareTo ( Turtle.MATURITY ) > 0 )
                {
                    anArbitraryMatureTurtle = Optional.of ( turtle );
                    break;
                }
            }
    

    对整个集合进行混洗可能不如随机选择索引那么高效。这可能是您选择随机索引方法的最初动机。但考虑到您可能的数据值,随机索引方法是不可行的。


    †错误……有一个解决方案可以解决该随机索引数字流方法。请参阅tquadrat 的正确答案。

    • 1
  2. Best Answer
    tquadrat
    2024-12-24T08:57:05+08:002024-12-24T08:57:05+08:00

    尝试在方法的逻辑部分中添加此操作,添加对和的main()调用。这样,我们以随机顺序覆盖所有可能的索引值一次。Stream#distinctStream#limit

    …
    // Logic
    Optional<Turtle> anArbitraryMatureTurtle = ThreadLocalRandom.current()
      .ints( 0, turtles.size() )
      .distinct()
      .limit( turtles.size() )
      .filter( (int randomIndex) -> turtles.get( randomIndex ).age().compareTo( Turtle.MATURITY ) > 0 )
      .mapToObj( turtles::get )
      .findAny();
    System.out.println( "anArbitraryMatureTurtle = " + anArbitraryMatureTurtle );
    …
    

    如果没有Turtle通过测试,我们得到一个空的Optional。

    代码序列:

    ThreadLocalRandom.current()
      .ints( 0, 5 )
      .distinct()
      .limit( 5 )
      .forEach( System.out::println );
    

    0…以随机顺序打印五个值4– 始终为五个,没有重复。当然,您必须turtles.size()根据用例使用 而不是常量5。

    我有些怀疑这是从您的列表中获取随机成年乌龟的最有效方法(假设有一只),但它确实有效。

    • 1

相关问题

  • Lock Condition.notify 抛出 java.lang.IllegalMonitorStateException

  • 多对一微服务响应未出现在邮递员中

  • 自定义 SpringBoot Bean 验证

  • Java 套接字是 FIFO 的吗?

  • 为什么不可能/不鼓励在服务器端定义请求超时?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行?

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    何时应使用 std::inplace_vector 而不是 std::vector?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Martin Hope
    Aleksandr Dubinsky 为什么 InetAddress 上的 switch 模式匹配会失败,并出现“未涵盖所有可能的输入值”? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge 为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini 具有指定基础类型但没有枚举器的“枚举类”的用途是什么? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer 何时应使用 std::inplace_vector 而不是 std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB 为什么 GCC 生成有条件执行 SIMD 实现的代码? 2024-02-17 06:17:14 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve