AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 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

Nenhum resultado ao filtrar em um IntStream aleatório, em Java

  • 772

Estou representando uma coleção de tartarugas, cada uma com um momento em que chocaram. Quero escolher aleatoriamente qualquer tartaruga madura.

Finjo que minutos são anos nesta simulação de aquário.

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

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

Eu costumo ThreadLocalRandomgerar um IntStreamde inteiros aleatórios. Eu uso esses inteiros como um índice em meus objetos Listde Turtle. Eu verifico a idade daquela tartaruga, para ver se ela excede a MATURITYduração predefinida. Se não estiver madura, deixo o fluxo continuar.

Claro, nenhuma tartaruga pode estar madura ainda. Então eu defini o tipo de retorno como Optional < Turtle >, para ser vazio se nenhuma tartaruga for encontrada.

O problema é que meu stream parece falhar, sem nenhum resultado retornado. Por quê?

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 respostas
  • 68 Views

2 respostas

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

    Infinito Streampode ser loop infinito

    Você inadvertidamente fez um loop infinito do seu infinito IntStream.

    Seu IntStreamcriado por ThreadLocalRandom.intsé infinito, gerando continuamente um número aleatório após o outro, dentro do seu intervalo definido. Duplicatas podem ocorrer, pois o número aleatório continua gerando até que seu fluxo alcance uma operação terminal.

    Você ligou findAnypara encerrar seu fluxo. Mas olhe para seus dados de amostra. Todas as suas tartarugas são jovens, onde nenhuma delas tem uma idade que atenda ao seu IntPredicateteste de exceder a MATURITYduração. Então nenhuma das suas tartarugas passa no teste de idade. Então o findAnynunca encontra nenhum Turtle, então ele nunca retorna nenhum Optional < Turtle >.

    Isso significa que a geração de números aleatórios continua moendo, produzindo um número de índice após o outro. Para cada número aleatório, acessamos os Listobjetos Turtle. Mas nenhum passa no nosso teste de predicado. Portanto, nosso fluxo nunca termina . Esta rotina de teste de predicado random-generator -> List#get-> continua infinitamente. O fluxo nunca termina, neste loop infinito, dando a aparência de que nada está acontecendo. Na verdade, muita coisa está acontecendo, com um núcleo de CPU muito ocupado gerando números, acessando a lista e calculando e comparando durações, infinitamente.

    Podemos demonstrar isso alterando seus dados de amostra. Inicie os peixes Bob& Daviscom hatch-dates de 7 minutos atrás em vez de 2 minutos. Execute seu código novamente para ver que qualquer um deles é escolhido aleatoriamente, e escolhido bem rápido.

            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 = Opcional[Tartaruga[nome=Davis, chocado=2024-12-23T21:17:00Z, tempo de vida=PT22M]]

    Solução

    Não há solução para consertar diretamente seu código atual † . Você não pode usar um fluxo infinito sem uma terminação garantida.

    Em vez disso, você deve reescrever seu código.

    Uma reescrita poderia ser fazer uma cópia de seus Listobjetos Turtle. Embaralhe-os, colocando a lista em ordem aleatória. Então transmita essa lista randomizada até que uma seja encontrada atendendo às condições do seu teste de predicado. Se nenhuma atender a essas condições, o fluxo termina após verificar exaustivamente cada elemento, e um vazio Optionalserá retornado.

    Altere sua seção Lógica para isto:

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

    Não há mais índice aleatório.

    Quando executado com todas as tartarugas jovens e imaturas:

    anArbitraryMatureTurtle = Opcional.vazio

    Essa mesma lógica poderia ser feita com um forloop convencional em vez de um Stream. Acho que a Streamsintaxe é mais expressiva neste caso em particular.

            // 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;
                }
            }
    

    Embaralhar uma coleção inteira provavelmente não é tão eficiente quanto escolher um índice aleatoriamente. Essa pode ter sido sua motivação original ao escolher a abordagem de índice aleatório. Mas, dados seus possíveis valores de dados, a abordagem de índice aleatório não é viável.


    † Errado… há uma solução que corrige essa abordagem de fluxo de números de índice aleatórios. Veja a resposta correta de tquadrat .

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

    Tente isso para a seção Logicmain() no seu método, adicionando chamadas para Stream#distincte Stream#limit. Dessa forma, cobrimos todos os valores de índice possíveis uma vez, em uma ordem aleatória.

    …
    // 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 );
    …
    

    Se nenhum Turtlepassar no teste, obtemos um . vazio Optional.

    A sequência de código:

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

    … imprime os cinco valores 0em 4uma ordem aleatória – sempre cinco, sem duplicatas. Claro que você tem que usar turtles.size()para seu caso de uso em vez da constante 5.

    Tenho algumas dúvidas de que esta seja a maneira mais eficiente de obter uma tartaruga adulta aleatória da sua lista (considerando que existe uma), mas funciona.

    • 1

relate perguntas

  • Lock Condition.notify está lançando java.lang.IllegalMonitorStateException

  • Resposta de microsserviço Muitos para Um não aparece no carteiro

  • Validação personalizada do SpringBoot Bean

  • Os soquetes Java são FIFO?

  • Por que não é possível / desencorajado definir um lado do servidor de tempo limite de solicitação?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

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

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve