Eu tenho uma situação onde o return
instrução aninhada em dois for
loops sempre será alcançada, teoricamente.
O compilador discorda e requer um return
declaração fora do for
loop. Eu gostaria de saber uma maneira elegante de otimizar esse método que está além do meu entendimento atual, e nenhuma das minhas tentativas de implementação de break parece funcionar.
Attached é um método de uma atribuição que gera inteiros aleatórios e retorna as iterações percorridas até que um segundo inteiro aleatório seja encontrado, gerado dentro de um intervalo passado para o método como um parâmetro int.
private static int oneRun(int range) {
int[] rInt = new int[range+1]; // Stores the past sequence of ints.
rInt[0] = generator.nextInt(range); // Inital random number.
for (int count = 1; count <= range; count++) { // Run until return.
rInt[count] = generator.nextInt(range); // Add randint to current iteration.
for (int i = 0; i < count; i++) { // Check for past occurence and return if found.
if (rInt[i] == rInt[count]) {
return count;
}
}
}
return 0; // Never reached
}
while(true)
loop em vez de indexado. Isso informa ao compilador que o loop nunca retornará.oneRun(0)
) e você verá que alcançará rapidamente o seu inacessívelreturn
nextInt
lança uma exceção pararange < 0
O único caso em que o retorno é alcançado é quandorange == 0
Respostas:
A heurística do compilador nunca permitirá que você omita o último
return
. Se você tiver certeza de que nunca será alcançado, eu o substituo por umthrow
para esclarecer a situação.fonte
throw new AssertionError("\"unreachable\" code reached");
throw
que nunca será alcançado. Com muita frequência, as pessoas apenas desejam aplicar rapidamente "uma solução para governar todos", sem pensar muito sobre o problema subjacente. Mas programar é muito mais do que apenas codificação. Especialmente quando se trata de algoritmos. Se você inspecionar (cuidadosamente) o problema fornecido, perceberá que pode fatorar a última iteração dofor
loop externo e, portanto, substituir o retorno "inútil" por um útil (veja esta resposta ).Como @BoristheSpider apontou, você pode garantir que a segunda
return
instrução seja semanticamente inacessível:Compila e funciona bem. E se você receber um,
ArrayIndexOutOfBoundsException
saberá que a implementação estava semanticamente errada, sem ter que lançar nada explicitamente.fonte
for(int count = 0; true; count++)
.true
:for(int count = 0; ; count++) …
while(true)
, pensei que talvez java seja um pouco mais rígido nesse aspecto. É bom saber que não havia necessidade de se preocupar ... Na verdade, eu gostotrue
muito mais da versão omitida : torna visualmente claro que não há absolutamente nenhuma condição para olhar para :-)Como você perguntou sobre a quebra de dois
for
loops, você pode usar um rótulo para fazer isso (veja o exemplo abaixo):fonte
returnValue
haveria falha na compilação porque pode ser usado não inicializado?Enquanto uma afirmação é uma boa solução rápida. Em geral, esse tipo de problema significa que seu código é muito complicado. Quando estou olhando para o seu código, é óbvio que você realmente não deseja que uma matriz contenha os números anteriores. Você quer um
Set
:Agora observe que o que estamos retornando é, na verdade, o tamanho do conjunto. A complexidade do código diminuiu de quadrática para linear e é imediatamente mais legível.
Agora podemos perceber que nem mesmo precisamos desse
count
índice:fonte
Como seu valor de retorno é baseado na variável do loop externo, você pode simplesmente alterar a condição do loop externo
count < range
e retornar este último valor (que você acabou de omitir) no final da função:Dessa forma, você não precisa introduzir um código que nunca será alcançado.
fonte
...
), mas o loop externo foi reduzido por sua última iteração. O caso correspondente a esta última iteração é tratado separadamente pela última instrução return. Embora esta seja uma solução elegante para o seu exemplo, existem cenários em que essa abordagem se torna mais difícil de ler; se, por exemplo, o valor de retorno dependesse do loop interno, então - em vez de uma única instrução de retorno no final - você ficaria com um loop adicional (representando o loop interno da última iteração do loop externo).Use uma variável temporária, por exemplo "resultado", e remova o retorno interno. Altere o loop for por um loop while com a condição adequada. Para mim é sempre mais elegante ter apenas um retorno como a última instrução da função.
fonte
return result
espalhados dentro dele e então pensam em querer fazer mais uma verificação no achadoresult
antes de devolvê-lo, e este é apenas um exemplo). Também pode haver contras, mas uma declaração tão ampla como "Em geral, não há uma boa razão para ter apenas um retorno" não é válida.Talvez isso seja uma indicação de que você deve reescrever seu código. Por exemplo:
fonte
Os métodos que possuem uma instrução de retorno e um loop / loops dentro deles sempre exigem uma instrução de retorno fora do (s) loop (s). Mesmo que essa instrução fora do loop nunca seja alcançada. Nesses casos, para evitar declarações de retorno desnecessárias, você pode definir uma variável do respectivo tipo, um inteiro no seu caso, no início do método, ou seja, antes e fora do (s) respectivo (s) loop (s). Quando o resultado desejado dentro do loop for alcançado, você pode atribuir o respectivo valor a essa variável predefinida e usá-lo para a instrução de retorno fora do loop.
Como você deseja que seu método retorne o primeiro resultado quando rInt [i] for igual a rInt [contagem], implementar apenas a variável mencionada acima não é suficiente porque o método retornará o último resultado quando rInt [i] for igual a rInt [contagem]. Uma das opções é implementar duas "instruções de interrupção" que são chamadas quando temos o resultado desejado. Portanto, o método será mais ou menos assim:
fonte
Concordo que se deve lançar uma exceção onde ocorre uma declaração inacessível. Só queria mostrar como o mesmo método pode fazer isso de maneira mais legível (streams java 8 necessários).
fonte
fonte
result == -1
cheques que podem ser omitidos com oreturn
dentro do loop ...