español - Última iteración de Enhanced for loop in java
for loop java español (21)
¿Hay alguna forma de determinar si el ciclo se está iterando por última vez? Mi código se ve así:
int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();
for(int i : array)
{
builder.append("" + i);
if(!lastiteration)
builder.append(",");
}
Ahora el problema es que no quiero agregar la coma en la última iteración. Ahora hay una manera de determinar si es la última iteración o estoy atrapado con el ciclo for o usando un contador externo para realizar un seguimiento.
Aquí hay una solución:
int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();
bool firstiteration=true;
for(int i : array)
{
if(!firstiteration)
builder.append(",");
builder.append("" + i);
firstiteration=false;
}
Busque la primera iteración :)
Como es una matriz fija, sería más fácil simplemente evitar la mejora para ... Si el Objeto es una colección, un iterador sería más fácil.
int nums[] = getNumbersArray();
StringBuilder builder = new StringBuilder();
// non enhanced version
for(int i = 0; i < nums.length; i++){
builder.append(nums[i]);
if(i < nums.length - 1){
builder.append(",");
}
}
//using iterator
Iterator<int> numIter = Arrays.asList(nums).iterator();
while(numIter.hasNext()){
int num = numIter.next();
builder.append(num);
if(numIter.hasNext()){
builder.append(",");
}
}
Como se menciona en el kit de herramientas, en Java 8 ahora tenemos Collectors . Así es como se vería el código:
String joined = array.stream().map(Object::toString).collect(Collectors.joining(", "));
Creo que eso hace exactamente lo que estás buscando, y es un patrón que puedes usar para muchas otras cosas.
Dos caminos alternativos aquí:
1: Apache Commons String Utils
2: mantener un booleano llamado first
, establecer en verdadero. En cada iteración, si la first
es falsa, agregue su coma; después de eso, establece first
en falso.
En base a java.util.AbstractCollection.toString (), sale temprano para evitar el delimitador.
StringBuffer buffer = new StringBuffer();
Iterator iter = s.iterator();
for (;;) {
buffer.append(iter.next());
if (! iter.hasNext())
break;
buffer.append(delimiter);
}
Es eficiente y elegante, pero no tan evidente como algunas de las otras respuestas.
En este caso, realmente no hay necesidad de saber si es la última repetición. Hay muchas maneras en que podemos resolver esto. Una forma sería:
String del = null;
for(int i : array)
{
if (del != null)
builder.append(del);
else
del = ",";
builder.append(i);
}
Este es un punto de referencia de SSCCE que ejecuté (relacionado con lo que tuve que implementar) con estos resultados:
elapsed time with checks at every iteration: 12055(ms)
elapsed time with deletion at the end: 11977(ms)
En mi ejemplo, al menos, omitir el cheque en cada iteración no es notablemente más rápido, especialmente para los volúmenes de datos, pero es más rápido.
import java.util.ArrayList;
import java.util.List;
public class TestCommas {
public static String GetUrlsIn(int aProjectID, List<String> aUrls, boolean aPreferChecks)
{
if (aPreferChecks) {
StringBuffer sql = new StringBuffer("select * from mytable_" + aProjectID + " WHERE hash IN ");
StringBuffer inHashes = new StringBuffer("(");
StringBuffer inURLs = new StringBuffer("(");
if (aUrls.size() > 0)
{
for (String url : aUrls)
{
if (inHashes.length() > 0) {
inHashes.append(",");
inURLs.append(",");
}
inHashes.append(url.hashCode());
inURLs.append("/"").append(url.replace("/"", "///"")).append("/"");//.append(",");
}
}
inHashes.append(")");
inURLs.append(")");
return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString();
}
else {
StringBuffer sql = new StringBuffer("select * from mytable" + aProjectID + " WHERE hash IN ");
StringBuffer inHashes = new StringBuffer("(");
StringBuffer inURLs = new StringBuffer("(");
if (aUrls.size() > 0)
{
for (String url : aUrls)
{
inHashes.append(url.hashCode()).append(",");
inURLs.append("/"").append(url.replace("/"", "///"")).append("/"").append(",");
}
}
inHashes.deleteCharAt(inHashes.length()-1);
inURLs.deleteCharAt(inURLs.length()-1);
inHashes.append(")");
inURLs.append(")");
return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString();
}
}
public static void main(String[] args) {
List<String> urls = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
urls.add("http://www.google.com/" + System.currentTimeMillis());
urls.add("http://www.yahoo.com/" + System.currentTimeMillis());
urls.add("http://www.bing.com/" + System.currentTimeMillis());
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < 300; i++) {
GetUrlsIn(5, urls, true);
}
long endTime = System.currentTimeMillis();
System.out.println("elapsed time with checks at every iteration: " + (endTime-startTime) + "(ms)");
startTime = System.currentTimeMillis();
for (int i = 0; i < 300; i++) {
GetUrlsIn(5, urls, false);
}
endTime = System.currentTimeMillis();
System.out.println("elapsed time with deletion at the end: " + (endTime-startTime) + "(ms)");
}
}
Esto es casi una repetición de esta pregunta de . Lo que quiere es StringUtils y llamar al método de unión .
StringUtils.join(strArr, '','');
Los bucles explícitos siempre funcionan mejor que los implícitos.
builder.append( "" + array[0] );
for( int i = 1; i != array.length; i += 1 ) {
builder.append( ", " + array[i] );
}
Debería envolver todo en una instrucción if en caso de que esté tratando con una matriz de longitud cero.
Muchas de las soluciones descritas aquí son un poco exageradas, en mi humilde opinión, especialmente aquellas que dependen de bibliotecas externas. Hay una agradable y clara expresión idiomática para lograr una lista separada por comas que siempre he usado. Se basa en el operador condicional (?):
Editar : solución original correcta, pero no óptima según los comentarios. Probando por segunda vez:
int[] array = {1, 2, 3};
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < array.length; i++)
builder.append(i == 0 ? "" : ",").append(array[i]);
Ahí va, en 4 líneas de código que incluyen la declaración de la matriz y el StringBuilder.
Necesita Class Separator .
Separator s = new Separator(", ");
for(int i : array)
{
builder.append(s).append(i);
}
La implementación del Separator
de clase es sencilla. Envuelve una cadena que se devuelve en cada llamada de toString()
excepto por la primera llamada, que devuelve una cadena vacía.
Otra alternativa es agregar la coma antes de agregar i, solo que no en la primera iteración. (Por cierto, no use "" + i
, por cierto, realmente no quiere concatenación aquí, y StringBuilder tiene una sobrecarga de apend (int) perfectamente buena).
int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();
for (int i : array) {
if (builder.length() != 0) {
builder.append(",");
}
builder.append(i);
}
Lo bueno de esto es que funcionará con cualquier Iterable
: no siempre se pueden indexar cosas. (La frase "agregue la coma y luego elimínela al final" es una buena sugerencia cuando realmente usa StringBuilder, pero no funciona para cosas como escribir en streams. Sin embargo, posiblemente sea el mejor enfoque para este problema exacto. )
Otra forma de hacer esto:
String delim = "";
for (int i : ints) {
sb.append(delim).append(i);
delim = ",";
}
Actualización: para Java 8, ahora tienes Collectors
Otra opción más
StringBuilder builder = new StringBuilder();
for(int i : array)
builder.append('','').append(i);
String text = builder.toString();
if (text.startsWith(",")) text=text.substring(1);
Otra solución (quizás la más eficiente)
int[] array = {1, 2, 3};
StringBuilder builder = new StringBuilder();
if (array.length != 0) {
builder.append(array[0]);
for (int i = 1; i < array.length; i++ )
{
builder.append(",");
builder.append(array[i]);
}
}
Otro enfoque es tener la longitud de la matriz (si está disponible) almacenada en una variable separada (más eficiente que volver a verificar la longitud cada vez). Luego puede comparar su índice con esa longitud para determinar si agrega o no la coma final.
EDITAR: Otra consideración es ponderar el costo de rendimiento de eliminar un carácter final (que puede causar una copia de cadena) en contra de tener un condicional se verifique en cada iteración.
Puede ser más fácil agregar siempre. Y luego, cuando hayas terminado con tu ciclo, simplemente elimina el personaje final. Tone menos condicionales de esa manera también.
Puede usar deleteCharAt(int index)
StringBuilder
con índice siendo length() - 1
Si lo convierte a un ciclo de índice clásico, sí.
O simplemente podría eliminar la última coma después de que haya terminado. Al igual que:
int[] array = {1, 2, 3...};
StringBuilder
builder = new StringBuilder();
for(int i : array)
{
builder.append(i + ",");
}
if(builder.charAt((builder.length() - 1) == '',''))
builder.deleteCharAt(builder.length() - 1);
Yo, solo uso StringUtils.join()
de commons-lang .
Si solo está convirtiendo una matriz en una matriz delimitada por comas, muchos lenguajes tienen una función de combinación para exactamente eso. Convierte una matriz en una cadena con un delimitador entre cada elemento.
Tal vez estás usando la herramienta incorrecta para el trabajo.
Esto es más manual que lo que estás haciendo, pero es de una manera más elegante si no es un poco "vieja escuela"
StringBuffer buffer = new StringBuffer();
Iterator iter = s.iterator();
while (iter.hasNext()) {
buffer.append(iter.next());
if (iter.hasNext()) {
buffer.append(delimiter);
}
}
manténgalo simple y use un ciclo estándar for:
for(int i = 0 ; i < array.length ; i ++ ){
builder.append(array[i]);
if( i != array.length - 1 ){
builder.append('','');
}
}
o simplemente usa apache commons-lang StringUtils.join ()