¿Hay alguna manera en el ciclo for-each de Java?
for(String s : stringArray) {
doSomethingWith(s);
}
para saber con qué frecuencia el ciclo ya ha sido procesado?
Además de usar el viejo y conocido for(int i=0; i < boundary; i++)
bucle, es la construcción
int i = 0;
for(String s : stringArray) {
doSomethingWith(s);
i++;
}
¿Cuál es la única manera de tener dicho contador disponible en un ciclo para cada uno?
Type var = null; for (var : set) dosomething; if (var != null) then ...
Respuestas:
No, pero puedes proporcionar tu propio contador.
La razón de esto es que el ciclo for-each internamente no tiene un contador; se basa en la interfaz Iterable , es decir, utiliza un
Iterator
bucle a través de la "colección", que puede no ser una colección en absoluto, y de hecho puede ser algo que no se basa en ningún índice (como una lista vinculada).fuente
for(int idx=0, String s; s : stringArray; ++idx) doSomethingWith(s, idx);
each_with_index
método de bucleEnumerable
en Ruby. Ver apidock.com/ruby/Enumerable/each_with_indexfor
ciclo", algo así comofor (int i = 0; String s: stringArray; ++i)
Hay otra manera
Dado que usted escribe su propia
Index
clase y un método estático que devuelve unaIterable
sobre instancias de esta clase, puedeDonde la implementación de
With.index
es algo así comofuente
La solución más fácil es simplemente ejecutar su propio contador así:
La razón de esto es porque no hay garantía real de que los elementos de una colección (que esa variante de
for
itera) incluso tengan un índice, o incluso tengan un orden definido (algunas colecciones pueden cambiar el orden cuando agrega o elimina elementos).Vea, por ejemplo, el siguiente código:
Cuando ejecutas eso, puedes ver algo como:
indicando que, con razón, el orden no se considera una característica destacada de un conjunto.
Hay otras formas de hacerlo sin un contador manual, pero es un buen trabajo para dudoso beneficio.
fuente
El uso de lambdas e interfaces funcionales en Java 8 hace posible la creación de nuevas abstracciones de bucle. Puedo recorrer una colección con el índice y el tamaño de la colección:
Qué salidas:
Lo que implementé como:
Las posibilidades son infinitas. Por ejemplo, creo una abstracción que usa una función especial solo para el primer elemento:
Que imprime una lista separada por comas correctamente:
Lo que implementé como:
Las bibliotecas comenzarán a aparecer para hacer este tipo de cosas, o puede rodar las suyas.
fuente
Java 8 introdujo el método
Iterable#forEach()
/Map#forEach()
, que es más eficiente para muchas implementacionesCollection
/ enMap
comparación con el ciclo "clásico" para cada bucle. Sin embargo, también en este caso no se proporciona un índice. El truco aquí es usarAtomicInteger
fuera de la expresión lambda. Nota: las variables utilizadas dentro de la expresión lambda deben ser efectivamente finales, es por eso que no podemos usar un ordinarioint
.fuente
Me temo que esto no es posible con
foreach
. Pero puedo sugerirle unos simples bucles for de estilo antiguo :Tenga en cuenta que la interfaz de Lista le da acceso a
it.nextIndex()
.(editar)
A su ejemplo cambiado:
fuente
Uno de los cambios que se
Sun
está considerandoJava7
es proporcionar acceso al interiorIterator
en bucles foreach. la sintaxis será algo así (si se acepta):Este es el azúcar sintáctico, pero aparentemente se hicieron muchas solicitudes para esta función. Pero hasta que se apruebe, tendrá que contar las iteraciones usted mismo o usar un ciclo regular para con un
Iterator
.fuente
Solución idiomática:
fuente
Aunque hay muchas otras formas mencionadas para lograr lo mismo, compartiré mi camino con algunos usuarios insatisfechos. Estoy usando la característica Java 8 IntStream.
1. Matrices
2. Lista
fuente
Si necesita un contador en un ciclo para cada uno, debe contar usted mismo. No hay un mostrador incorporado hasta donde yo sé.
fuente
Hay una "variante" para la respuesta de pax ... ;-)
fuente
i=0; i++;
enfoque aparentemente más claro ?Para situaciones en las que solo necesito el índice ocasionalmente, como en una cláusula catch, a veces usaré indexOf.
fuente
La solución mejor y optimizada es hacer lo siguiente:
Donde Tipo puede ser cualquier tipo de datos y tipos es la variable en la que está solicitando un bucle.
fuente
Estoy un poco sorprendido de que nadie sugirió lo siguiente (admito que es un enfoque perezoso ...); Si stringArray es una lista de algún tipo, podría usar algo como stringArray.indexOf (S) para devolver un valor para el recuento actual.
Nota: esto supone que los elementos de la Lista son únicos, o que no importa si no son únicos (porque en ese caso devolverá el índice de la primera copia encontrada).
Hay situaciones en las que eso sería suficiente ...
fuente
Aquí hay un ejemplo de cómo hice esto. Esto obtiene el índice en cada ciclo. Espero que esto ayude.
fuente