valores usar sentencia retornar retornan que metodos metodo example estaticos cuando java

usar - ¿Cómo evito un retorno inútil en un método Java?



retornar dos valores en java (10)

Tengo una situación en la que la declaración de return anidada en dos bucles for siempre se alcanzará, teóricamente.

El compilador no está de acuerdo y requiere una declaración de return fuera del ciclo for . Me gustaría conocer una manera elegante de optimizar este método que está más allá de mi comprensión actual, y ninguna de mis intentos de implementación de break parece funcionar.

Se adjunta un método a partir de una asignación que genera enteros aleatorios y devuelve las iteraciones cicladas hasta que se encuentra un segundo entero aleatorio, generado dentro de un rango pasado al método como un 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 }


Como señaló @BoristheSpider, puede asegurarse de que la segunda declaración de return sea ​​semánticamente inalcanzable:

private static int oneRun(int range) { int[] rInt = new int[range+1]; // Stores the past sequence of ints. int count = 0; while (true) { 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; } } count++; } }

Compila y corre bien. Y si alguna vez obtiene una ArrayIndexOutOfBoundsException , sabrá que la implementación fue semánticamente incorrecta, sin tener que arrojar nada explícitamente.


Como su valor de retorno se basa en la variable del bucle externo, simplemente puede alterar la condición del bucle externo para count < range y luego devolver este último valor (que acaba de omitir) al final de la función:

private static int oneRun(int range) { ... for (int count = 1; count < range; count++) { ... } return range; }

De esta manera, no necesita introducir código que nunca se alcanzará.


Como usted preguntó acerca de romper dos bucles for , puede usar una etiqueta para hacerlo (vea el ejemplo a continuación):

private static int oneRun(int range) { int returnValue=-1; int[] rInt = new int[range+1]; // Stores the past sequence of ints. rInt[0] = generator.nextInt(range); // Inital random number. OUTER: 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]) { returnValue = count; break OUTER; } } } return returnValue; }


Estoy de acuerdo en que uno debe lanzar una excepción cuando se produce una declaración inalcanzable Solo quería mostrar cómo el mismo método puede hacer esto de una manera más legible (se requieren java 8 streams).

private static int oneRun(int range) { int[] rInt = new int[range + 1]; return IntStream .rangeClosed(0, range) .peek(i -> rInt[i] = generator.nextInt(range)) .filter(i -> IntStream.range(0, i).anyMatch(j -> rInt[i] == rInt[j])) .findFirst() .orElseThrow(() -> new RuntimeException("Shouldn''t be reached!")); }


La heurística del compilador nunca te permitirá omitir el último return . Si está seguro de que nunca se alcanzará, lo reemplazaría con un throw para aclarar la situación.

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++) { ... } throw new AssertionError("unreachable code reached"); }


Los métodos que tienen una declaración de retorno y tienen un bucle / bucles dentro de ellos siempre requieren una declaración de retorno fuera del bucle (s). Incluso si esta declaración fuera del ciclo nunca se alcanza. En tales casos, para evitar declaraciones de retorno innecesarias, puede definir una variable del tipo respectivo, un número entero en su caso, al comienzo del método, es decir, antes y fuera del bucle o bucles respectivos. Cuando se alcanza el resultado deseado dentro del ciclo, puede atribuir el valor respectivo a esta variable predefinida y usarlo para la declaración de retorno fuera del ciclo.

Como desea que su método devuelva el primer resultado cuando rInt [i] es igual a rInt [count], implementar solo la variable mencionada anteriormente no es suficiente porque el método devolverá el último resultado cuando rInt [i] es igual a rInt [count]. Una opción es implementar dos "declaraciones de interrupción" que se llaman cuando tenemos el resultado deseado. Entonces, el método se verá más o menos así:

private static int oneRun(int range) { int finalResult = 0; // the above-mentioned variable int[] rInt = new int[range + 1]; rInt[0] = generator.nextInt(range); for (int count = 1; count <= range; count++) { rInt[count] = generator.nextInt(range); for (int i = 0; i < count; i++) { if (rInt[i] == rInt[count]) { finalResult = count; break; // this breaks the inside loop } } if (finalResult == count) { break; // this breaks the outside loop } } return finalResult; }


Si bien una afirmación es una buena solución rápida. En general, este tipo de problemas significa que su código es demasiado complicado. Cuando miro su código, es obvio que realmente no desea que una matriz contenga números anteriores. Quieres un Set :

Set<Integer> previous = new HashSet<Integer>(); int randomInt = generator.nextInt(range); previous.add(randomInt); for (int count = 1; count <= range; count++) { randomInt = generator.nextInt(range); if (previous.contains(randomInt)) { break; } previous.add(randomInt); } return previous.size();

Ahora tenga en cuenta que lo que estamos devolviendo es en realidad el tamaño del conjunto. La complejidad del código ha disminuido de cuadrática a lineal e inmediatamente es más legible.

Ahora podemos darnos cuenta de que ni siquiera necesitamos ese índice de count :

Set<Integer> previous = new HashSet<Integer>(); int randomInt = generator.nextInt(range); while (!previous.contains(randomInt)) { previous.add(randomInt); randomInt = generator.nextInt(range); } return previous.size();


Tal vez esto sea una indicación de que debería reescribir su código. Por ejemplo:

  1. Cree una matriz de enteros 0 .. rango-1. Establezca todos los valores a 0.
  2. Realizar un bucle. En el ciclo, genera un número aleatorio. Mire en su lista, en ese índice, para ver si el valor es 1 Si es así, salga del ciclo. De lo contrario, establezca el valor en ese índice en 1
  3. Cuente el número de 1s en la lista y devuelva ese valor.

Utilice una variable temporal, por ejemplo "resultado", y elimine el retorno interno. Cambie el ciclo for por un ciclo while con la condición adecuada. Para mí, siempre es más elegante tener solo un retorno como la última declaración de la función.


private static int oneRun(int range) { int result = -1; // use this to store your result 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 && result == -1; count++) { // Run until result found. rInt[count] = generator.nextInt(range); // Add randint to current iteration. for (int i = 0; i < count && result == -1; i++) { // Check for past occurence and leave after result found. if (rInt[i] == rInt[count]) { result = count; } } } return result; // return your result }