6. Iteración: for clásico sobre arrays y Strings
UD3 — Control de Flujo y Depuración · RA3 — Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje
IES Thiar — Pilar de la Horadada (Alicante) · Curso 2026-2027
| Aspecto | Valor |
|---|---|
| Resultado de aprendizaje | RA: 3 — Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje. |
| Criterios de evaluación a los que contribuye esta sección | CE 3.2 (utiliza estructuras de repetición) CE 3.5 (crea programas ejecutables combinando estructuras de control) CE 3.7 (comenta y documenta el código). |
| Marco normativo | RD 405/2023 · RD 450/2010 · RD 659/2023 |
| Tecnología base | Java 25 LTS (OpenJDK Temurin 25) — soporte hasta 2030+ |
| Horas estimadas | ~2 h (de las 30 h de la UD3). |
Requisitos previos (lo que ya sabes): condiciones booleanas y operadores lógicos (sección 1 de UD3);
if/else if/else, early return, validación conIO.readlnyString.matches(sección 2 de UD3);switchexpression con flecha y múltiples etiquetas (sección 3 de UD3);whileydo-while(sección 4 de UD3); arrays unidimensionales como tipo compuesto (declaración con{ }y connew Tipo[n],.length, acceso por índice, valores por defecto,String.toCharArray(), swap) — todo eso se introdujo en la sección 5 de UD3. Importante: en la sección 5 se introdujo el tipo array en sí, pero no se recorrió con bucles (los pocos recorridos se hicieron conwhile, que ya conocías). Elforclásico se introduce ahora, en esta sección 6, como la herramienta natural para recorrer arrays. Tipos primitivos,var,String(con.equals(),.equalsIgnoreCase(),.length(),.trim(),.toLowerCase(),.matches(),.charAt()),text blocks,finalpara constantes y operador ternario (de UD1).
6.1 ¿De qué va esta sección? — El bucle versátil, en profundidad
En la sección 5 aprendiste los arrays unidimensionales como tipo compuesto: cómo se crean, cómo se inicializan y cómo se accede a sus elementos sueltos. Para los pocos recorridos que necesitaste, usaste while con un índice i y tuviste que acordarte del i++ al final del cuerpo. Es funcional pero verboso, y es muy fácil olvidar el i++ y provocar un bucle infinito.
En esta sección vas a conocer el for clásico: un bucle que agrupa inicialización + condición + actualización en una sola línea, lo que lo hace mucho más cómodo y seguro para recorrer arrays. Es el bucle natural para "pasar por todos los elementos de un array" (o de un String), y es la herramienta que vas a usar el 80 % de las veces que necesites iterar.
El for clásico no es más potente que el while (ambos son bucles con condición), pero es mucho más cómodo para el caso típico de "recorrer N elementos": te obliga a poner la inicialización, la condición y la actualización en la misma línea, así que no puedes olvidar ninguna de las tres. Y además tiene variantes que cubren casos especiales: recorrer al revés, saltar elementos, recorrer dos arrays a la vez, etc.
En esta sección vamos a introducir el for clásico desde cero y a profundizar en todas sus variantes. Cubriremos, en este orden:
- Anatomía detallada del
for: las tres partes (inicialización, condición, actualización). - El patrón estándar:
for (int i = 0; i < arr.length; i++)— introducción al recorrido de arrays. - Variante 1: decreciente — recorrer al revés.
- Variante 2: con saltos —
i += 2,i *= 2, etc. - Variante 3: múltiples variables —
for (int i = 0, j = n-1; i < j; i++, j--). - Variante 4: condición compleja —
i < n && !encontrado. - Variante 5: sin alguna de las tres partes —
for (;;),for (; i < n; ), etc. forsobre Strings concharAt(i)— recorrer caracteres sin convertir a array.forsobre arrays de distintos tipos —int[],double[],String[],char[].forvs.while: criterios de elección.- Trampas clásicas del
for. - Ejemplos resueltos paso a paso.
Analogía del contador de parking
El for clásico es como el contador automático de un parking: cada vez que entra un coche, sube una unidad; cuando llega al aforo máximo, se para. Tú configuras tres cosas: dónde empieza el contador (0), cuándo se para (< aforo), y cuánto sube en cada paso (+1). Pero también podrías configurarlo para que cuente atrás (de aforo a 0), que salte de 2 en 2 (si cada coche ocupa 2 plazas), o que cuente dos cosas a la vez (coches y motos). Esa flexibilidad es lo que hace el for clásico tan potente.
Vamos a empezar por despiezar el for parte por parte, para que veas por qué cada una existe y qué permite.
6.2 Anatomía detallada del for clásico
6.2.1 Las tres partes
La sintaxis general del for es:
Cada una de las tres partes entre paréntesis tiene un papel:
| Parte | Qué hace | Cuándo se ejecuta |
|---|---|---|
| Inicialización | Prepara variables (normalmente el índice i). |
Una sola vez, antes de la primera comprobación. |
| Condición | Expresión booleana evaluada antes de cada iteración. Si es true, se ejecuta el cuerpo; si es false, se sale. |
Antes de cada iteración (incluida la primera). |
| Actualización | Modifica variables (normalmente i++). |
Después del cuerpo, antes de la siguiente comprobación. |
6.2.2 Flujo de ejecución
flowchart TD
Inicio([Inicio]) --> Init["Inicialización\n(p. ej. int i = 0)"]
Init --> Cond{"¿Condición?\n(p. ej. i < arr.length)"}
Cond -->|true| Cuerpo["Cuerpo del bucle"]
Cuerpo --> Update["Actualización\n(p. ej. i++)"]
Update --> Cond
Cond -->|false| Fin([Fin del bucle])
Detalles clave:
- La inicialización se ejecuta una sola vez, al principio. No se repite.
- La condición se evalúa antes de cada iteración, incluida la primera. Si ya es
falseal empezar, el cuerpo no se ejecuta ni una vez. - La actualización se ejecuta después del cuerpo, antes de la siguiente comprobación. Es lo que hace que el bucle "avance".
- El orden es: init → cond → cuerpo → update → cond → cuerpo → update → ... → cond (false) → salir.
6.2.3 Las tres partes son opcionales, pero los puntos y comas no
Curiosamente, puedes dejar vacía cualquiera de las tres partes del for, pero los dos puntos y comas que las separan son obligatorios. Verás casos en la sección 6.7.
Estas variantes son poco habituales (salvo el for (;;) que verás en bucles con break), pero conviene que las conozcas porque las vas a encontrar en código de otros.
6.2.4 Ámbito de la variable del for
La variable i declarada en la inicialización existe solo dentro del for (incluyendo la condición, la actualización y el cuerpo). Fuera del bucle, i no existe:
Si necesitas usar i después del bucle, decláralo fuera:
Pero esto es poco habitual: lo normal es declarar i dentro del for y olvidarte de él al terminar.
6.2.5 Varios índices en una sola inicialización
La inicialización puede declarar varias variables del mismo tipo, separadas por comas:
Esto lo verás en detalle en la sección 6.6 (múltiples variables). Por ahora quédate con que sí se puede, y que las variables tienen que ser del mismo tipo (no puedes declarar int i, double j en la misma inicialización).
6.3 El patrón estándar: recorrer un array por primera vez
Antes de ver las variantes, veamos el patrón estándar del for clásico, que es lo primero que necesitas aprender para recorrer un array. Compararemos con el while que ya conoces de la sección 5, para que veas por qué el for es más cómodo.
6.3.1 Recorrer un array con while (lo que ya sabes)
En la sección 5, cuando necesitaste recorrer un array (por ejemplo, para pedir 5 edades y guardarlas), usaste while con un índice i:
Salida:
Esto funciona, pero requiere cuatro decisiones del programador, dispersas en tres líneas:
int i = 0declarado fuera del bucle.i < numeros.lengthcomo condición.i++al final del cuerpo (¡fácil de olvidar! → bucle infinito).numeros[i]en el cuerpo para acceder al elemento.
6.3.2 El mismo recorrido con for clásico
Salida idéntica. Pero ahora, las tres primeras decisiones (int i = 0, i < numeros.length, i++) están agrupadas en la primera línea del for:
Esto es lo que hace el for más seguro: no puedes olvidar el i++, porque va en la cabecera, no en el cuerpo. Y no puedes confundir el orden de las partes, porque la sintaxis te obliga a ponerlas en el orden correcto.
6.3.3 Las cuatro decisiones del patrón estándar
int i = 0: empezamos en 0 porque los índices de los arrays empiezan en 0 (lo viste en la sección 5).i < primos.length: usamos<(no<=) porque el último índice válido eslength - 1(también lo viste en la sección 5).i++: incrementamos de 1 en 1.primos[i]: accedemos al elemento actual usando el índice.
6.3.4 Recorrer un array de principio a fin con índice visible
Salida:
Aquí vemos el patrón más básico: recorrer un array imprimiendo cada elemento con su índice. Es la introducción al recorrido de arrays con for clásico.
6.3.5 Acumular (suma, producto, etc.)
El patrón más clásico: recorrer un array acumulando un valor.
Detalles:
sumase declara fuera del bucle (si la declararas dentro, se reiniciaría en cada iteración).suma = 0porque sumamos; si multiplicáramos, empezaríamos en1.suma = suma + numeros[i]también se puede escribirsuma += numeros[i](asignación compuesta).
6.3.6 Buscar el máximo
Aquí empezamos en i = 1 (no en 0) porque numeros[0] ya es el máximo inicial. Es una pequeña variante del patrón estándar.
6.3.7 Modificar elementos
El for clásico es la primera herramienta que ves que te permite modificar un array durante el recorrido. En la sección 5 solo accediste a elementos sueltos; aquí puedes recorrerlos todos y cambiarlos:
Aquí numeros[i] = numeros[i] * 2 es escritura sobre el elemento actual del array, no una copia. En la sección 7 verás que el for-each no puede hacer esto (la variable del for-each es una copia, no una referencia al elemento del array).
6.3.8 Imprimir con índice
Salida:
Fíjate en (i + 1): como los índices empiezan en 0, sumamos 1 al índice para mostrar "1, 2, 3" en vez de "0, 1, 2". Truco típico cuando presentas datos al usuario.
6.4 Variante 1: decreciente (recorrer al revés)
A veces necesitas recorrer un array del final al principio. Por ejemplo, para mostrar los elementos en orden inverso, o para某些 algoritmos de eliminación.
6.4.1 Sintaxis
Tres cambios respecto al patrón estándar:
i = arr.length - 1: empezamos por el último índice válido.i >= 0: continuamos mientrasisea mayor o igual que 0 (cuando llega a -1, salimos).i--: decrementamos en cada paso (en vez dei++).
6.4.2 Ejemplo: imprimir al revés
Salida:
6.4.3 Ejemplo: invertir un array in-place
Este ejemplo usa múltiples variables (ver 6.6) y el patrón swap (intercambio con temp). Es un algoritmo clásico para invertir un array sin crear uno nuevo.
6.4.4 Trampa: i > 0 vs i >= 0
Es la trampa simétrica a i < length vs i <= length. Aquí: si quieres incluir el índice 0, usa >= 0, no > 0.
6.5 Variante 2: con saltos
No tienes que ir de 1 en 1. Puedes saltar de k en k cambiando la actualización.
6.5.1 Saltar de 2 en 2
i += 2 es la actualización con salto. La condición i < numeros.length sigue siendo la misma. El cuerpo solo se ejecuta para i = 0, 2, 4, 6 (los pares).
6.5.2 Saltar de 3 en 3
6.5.3 Doble del índice (recorrido logarítmico)
i *= 2 duplica i en cada paso. Útil para algoritmos de búsqueda binaria o recorrido exponencial (los verás en UD6 con estructuras avanzadas).
6.5.4 Casos de uso típicos
| Salto | Caso de uso |
|---|---|
i += 2 |
Recorrer posiciones pares (o impares si empiezas en 1). |
i += 3 |
Recorrer de 3 en 3 (p. ej. agrupar de tres en tres). |
i *= 2 |
Recorrido exponencial (p. ej. búsqueda binaria). |
i /= 2 |
Recorrido desde el final hacia la mitad (en algoritmos de división). |
6.5.5 Trampa: la condición debe ser coherente con el salto
Con i += 2 (o cualquier salto > 1), i puede "saltarse" exactamente el valor length y caer en length + 1, lo cual sigue dando ArrayIndexOutOfBoundsException. Sigue usando <, no <=.
6.6 Variante 3: múltiples variables
La inicialización y la actualización pueden manejar varias variables a la vez.
6.6.1 Sintaxis
- Inicialización:
int i = 0, j = n - 1— declara dos variablesinten una sola línea. - Condición:
i < j— se cumple mientras no se crucen. - Actualización:
i++, j--— incrementaiy decrementaja la vez.
6.6.2 Regla: variables del mismo tipo
Solo puedes declarar varias variables del mismo tipo en una sola inicialización. No puedes mezclar tipos:
6.6.3 Ejemplo: invertir un array
Ya lo vimos en 6.4.3. Es el caso clásico de múltiples variables: i avanza desde el principio, j retrocede desde el final, se cruzan en el medio.
6.6.4 Ejemplo: recorrer dos arrays a la vez en paralelo
Aquí solo declaramos i (un solo índice), pero usamos nombres[i] y edades[i] para acceder a ambos arrays en paralelo. Es un patrón muy común cuando tienes arrays paralelos (dos arrays cuyos elementos en la misma posición están relacionados).
Cuidado con los arrays paralelos
Los arrays paralelos son una mala práctica en POO: cuando veas clases en UD4, lo natural será tener una clase Alumno con nombre y edad juntos, en vez de dos arrays separados. Pero mientras no conozcas POO, los arrays paralelos con for clásico son la forma de resolver el problema.
6.6.5 Ejemplo: palíndromo
Comprobar si un array (o un String) es palíndromo (se lee igual al derecho y al revés) usando múltiples variables:
Salida:
Aquí usamos i desde el principio y j desde el final, comparando charAt(i) con charAt(j). Si todos coinciden hasta cruzarse, es palíndromo.
6.7 Variante 4: condición compleja
La condición del for puede ser cualquier expresión booleana, no solo i < n.
6.7.1 Con un && para salir antes
Aquí la condición es i < numeros.length && !encontrado. El bucle sigue mientras no se acabe el array Y no se haya encontrado. En cuanto se encuentra (o se acaba el array), sale. Es una forma de "salir antes" sin usar break (que verás en la sección 8).
6.7.2 Con un || para condición alternativa
Menos común, pero posible.
6.7.3 Con una llamada a método
Aquí esValido(arr[i]) es una llamada a un método que devuelve boolean. La condición se evalúa en cada iteración, así que el método se llama en cada comprobación.
6.8 Variante 5: sin alguna de las tres partes
Como adelantamos en 6.2.3, puedes dejar vacía cualquiera de las tres partes.
6.8.1 Sin inicialización (variable ya declarada)
Útil cuando necesitas usar i después del bucle.
6.8.2 Sin actualización (hecha en el cuerpo)
Útil cuando la actualización no es trivial (p. ej., depende de una condición).
6.8.3 Sin condición: for (;;) — bucle infinito
Es equivalente a while (true). Lo verás combinado con break en la sección 8, en el patrón "menú interactivo con while (true) + break". Por ahora no lo uses; prefiere while (true) que es más legible.
6.8.4 Sin inicialización ni actualización (equivalente a while)
Si te encuentras escribiendo esto, probablemente querías un while (ver 6.10).
6.9 for sobre Strings con charAt(i)
Ya viste en la sección 5 que puedes convertir un String en char[] con toCharArray() y luego acceder a sus caracteres sueltos por índice. Aquí verás cómo recorrerlos con for (cosa que no hicimos en la sección 5, donde solo accedimos a elementos sueltos). Además verás una alternativa que no crea un array nuevo: usar charAt(i) directamente sobre el String.
6.9.1 Sintaxis
Diferencias con respecto a recorrer un array:
texto.length()(con paréntesis: es método), notexto.length(sin paréntesis: campo de array).texto.charAt(i)para acceder al carácter, notexto[i](los Strings no se pueden indexar directamente).
6.9.2 Ejemplo: imprimir cada carácter en una línea
Salida:
6.9.3 Ejemplo: contar vocales con charAt
Salida con "Hola, mundo":
6.9.4 charAt vs toCharArray: ¿cuándo usar cada uno?
| Criterio | charAt(i) |
toCharArray() + for |
|---|---|---|
| ¿Crea un array nuevo? | No (más eficiente en memoria). | Sí (crea un char[] nuevo). |
| ¿Sintaxis? | texto.charAt(i), un poco más verboso. |
arr[i], más limpio dentro del for. |
| ¿Permite for-each (sección 7)? | No, los String no se pueden recorrer con for-each directamente. |
Sí, una vez convertido a char[] puedes usar for-each sobre él. |
| ¿Recomendado para... | Recorridos simples, eficiencia en memoria. | Casos donde quieres usar for-each o modificar el array (raro en Strings). |
Regla del profesor:
Para recorrer un
Stringconforclásico, usacharAt(i)(más eficiente, sin crear array). Si quieres usar for-each (sección 7), entonces sí convierte contoCharArray().
6.9.5 Trampa: índice fuera de rango en charAt
Atención: aunque el String lanza StringIndexOutOfBoundsException (no ArrayIndexOutOfBoundsException), el concepto es el mismo: índices fuera de rango. Verás cómo manejar esta excepción en la sección 9.
6.9.6 Recorrer un String al revés
Aquí combinamos dos cosas: la variante decreciente (6.4) y el acceso con charAt. Es el patrón estándar para invertir un String.
6.10 for vs. while: criterios de elección
El for clásico y el while pueden hacer lo mismo (ambos son bucles con condición), pero tienen casos de uso distintos. Elegir bien al principio te ahorra bugs y mejora la legibilidad.
6.10.1 Tabla comparativa
| Criterio | for |
while |
|---|---|---|
| ¿Sabes cuántas iteraciones vas a hacer? | Sí, usa for. | No, usa while. |
| ¿Necesitas un índice? | Sí, for es natural. | Posible, pero verboso (declarar antes, incrementar dentro). |
¿La actualización es trivial (i++)? |
For, más limpio. | While, más verboso. |
| ¿La actualización es compleja (depende del cuerpo)? | For con actualización vacía. | While, más natural. |
¿Bucle infinito con salida interna (con break)? |
for (;;) posible pero raro. |
while (true) es la forma idiomática. |
| ¿Recorrer colección/array? | Sí, for clásico. | Posible, pero menos natural. |
| ¿Mientras no cambie una condición externa? | Posible con condición compleja. | Sí, while es natural. |
6.10.2 La regla de oro
"Si sabes cuántas iteraciones, usa
for. Si depende de una condición que cambia, usawhile."
Ejemplos:
6.10.3 Regla secundaria
"Si necesitas un índice,
fores más natural; si no,whilesuele ser más legible."
Ejemplos:
6.10.4 Cuándo uno se convierte en el otro
Cualquier for se puede reescribir como while y viceversa. Lo importante es elegir el que mejor comunica la intención:
Si te encuentras escribiendo un for con la inicialización y actualización vacías, eso es señal de que querías un while. Y viceversa: si tu while tiene un contador i que siempre se incrementa, eso es señal de que querías un for.
6.10.5 Diagrama de decisión
flowchart TD
A["¿Vas a recorrer algo N veces?"] --> B{"¿Conoces N\nantes de empezar?"}
B -->|Sí| C["**for clásico**"]
B -->|No, depende de una condición| D["**while**"]
C --> E{"¿Necesitas índice?"}
E -->|Sí| F["for con i"]
E -->|No, solo recorrer en orden| G["considera for-each (sección 7)"]
D --> H["while con condición"]
F --> Fin([Fin])
G --> Fin
H --> Fin
6.11 Trampas comunes del for clásico
Antes de pasar a los ejemplos, repasamos las trampas más típicas.
6.11.1 Trampa 1: < vs <= con length
Ya la vimos en la sección 5. La trampa nº 1 con arrays: usar <= en vez de <.
6.11.2 Trampa 2: i > 0 vs i >= 0 al recorrer al revés
6.11.3 Trampa 3: olvidar la actualización
6.11.4 Trampa 4: la variable del for no existe fuera
6.11.5 Trampa 5: condiciones con && que cortan antes de tiempo
Esto no es un bug si tu intención era parar en cuanto encontraras. Pero asegúrate de que es eso lo que querías, no "procesar todos Y de paso buscar".
6.11.6 Trampa 6: confundir length y length() según el tipo
Memoriza: array → length, String → length(). Ya lo vimos en la sección 5, pero conviene repetirlo porque es la fuente nº 1 de errores de compilación con bucles.
6.11.7 Trampa 7: múltiples variables de tipos distintos
6.11.8 Resumen de trampas
| Trampa | Síntoma | Solución |
|---|---|---|
<= vs < con length |
ArrayIndexOutOfBoundsException. |
Usar <. |
> 0 vs >= 0 al revés |
Se salta el índice 0. | Usar >= 0. |
Olvidar i++ |
Bucle infinito. | Ponerlo en la actualización o en el cuerpo. |
i no existe fuera |
Error de compilación. | Declarar i antes del for si lo necesitas fuera. |
&& que corta antes |
Procesamiento incompleto. | Asegurar que es la intención (parar al encontrar). |
length vs length() |
Error de compilación. | Array → length, String → length(). |
| Múltiples variables de tipos distintos | Error de compilación. | Declarar uno fuera. |
6.12 Ejemplos resueltos paso a paso
Cinco ejemplos completos que integran todo lo aprendido.
6.12.1 Ejemplo 1: tabla de multiplicar (variantes estándar)
Salida:
Puntos clave:
for (int i = 1; i <= 10; i++): empezamos en 1 (no en 0) porque las tablas empiezan en 1, y usamos<=(no<) porque queremos incluir el 10.- Aquí no recorremos un array, solo iteramos del 1 al 10. Por eso la condición es
<= 10(noi < arr.length). Es una decisión distinta a la del patrón estándar de arrays.
6.12.2 Ejemplo 2: invertir un array in-place (múltiples variables)
Salida:
Puntos clave:
- Múltiples variables:
int i = 0, j = numeros.length - 1en la inicialización. - Condición
i < j: para cuando se cruzan (no hace falta procesar el centro dos veces). - Actualización doble:
i++, j--(avanza uno, retrocede el otro). - Swap con
temppara no perder el valor al intercambiar. - In-place: no crea un array nuevo, modifica el original.
6.12.3 Ejemplo 3: recorrer un String al revés (variante decreciente + charAt)
Salida con "Hola":
Puntos clave:
texto.length()(con paréntesis, es método).- Variante decreciente: empezamos en
length() - 1, vamos hasta>= 0, decrementando coni--. texto.charAt(i)para acceder al carácter en la posiciónisin crear un array nuevo.- Concatenación
invertido = invertido + ...para construir el String resultado. En UD2 verásStringBuilderpara hacerlo más eficiente.
6.12.4 Ejemplo 4: recorrer dos arrays en paralelo
Salida:
Puntos clave:
- Un solo índice
ipara ambos arrays. Usamosnombres[i]yedades[i]en cada iteración. - Condición
i < nombres.length: asumimos que ambos arrays tienen la misma longitud. Si no, esto es un bug (ver 6.12.5). - Patrón de arrays paralelos: dos arrays cuyos elementos en la misma posición están relacionados. Cuando veas POO (UD4), lo natural será una clase
Alumnoconnombreyedadjuntos.
6.12.5 Ejemplo 5: contar vocales con charAt y condición compleja
Salida con "Hola mundo. Adios.":
Puntos clave:
- Condición compleja:
i < texto.length() && texto.charAt(i) != '.'. El bucle se detiene cuando se acaba el String o cuando encuentra un punto. charAt(i)dos veces en la condición y en el cuerpo: Java lo llama en cada acceso, pero es eficiente (no crea nada nuevo).- Cuenta las vocales solo hasta el punto, ignorando el resto. Es el patrón "parar en condición".
6.13 Buenas prácticas con el for clásico
6.13.1 Las 10 reglas del for profesional
- Usa
<conlength, no<=(la trampa nº 1). - Usa
>= 0al recorrer al revés, no> 0. - No olvides la actualización (
i++o equivalente). Sin ella, bucle infinito. - Declara
identro delforsalvo que la necesites fuera. - El patrón estándar
for (int i = 0; i < arr.length; i++)es el 80 % de los casos. Solo usa variantes cuando de verdad las necesites. - Múltiples variables solo cuando es necesario (invertir, recorrer dos arrays). No abuses.
charAt(i)para Strings con for clásico (más eficiente quetoCharArray); reservatoCharArraypara for-each (sección 7).length(array, sin paréntesis) vslength()(String, con paréntesis). Memorízalo.- Si sabes cuántas iteraciones, usa
for. Si no,while. Es la regla de oro. - Comenta las variantes no estándar: si pones
i += 2o múltiples variables, un comentario breve ayuda al lector.
6.13.2 Cuándo refactorizar
| Síntoma | Refactoriza a |
|---|---|
for con init y update vacíos. |
while (más natural para tu caso). |
for (int i = 0; i < arr.length; i++) solo para recorrer sin tocar i. |
for-each (sección 7, más legible). |
while (true) con contador i++ siempre. |
for (int i = 0; ...) (más natural). |
for con condición && compleja. |
Considera break (sección 8) si la intención es "parar en cuanto". |
| Recorrer dos arrays paralelos. | Cuando veas POO (UD4): clase con ambos campos. |
6.13.3 Comentar el for
Los comentarios buenos en un for explican la intención del recorrido, no el bucle en sí:
6.14 Resumen y mapa conceptual
6.14.1 Mapa conceptual
mindmap
root((Sección 6 - for clásico))
Anatomía
Inicialización
Condición
Actualización
Las 3 opcionales
Ambito de i
Patrón estándar
i = 0; i length; i++
Acumular
Buscar máximo
Modificar
Variantes
Decreciente al revés
Con saltos i += 2
Múltiples variables
Condición compleja
Sin alguna parte for (;;)
Sobre Strings
charAt i
length con paréntesis
Recorrer al revés
Sobre arrays
int double String char
Recorrer modificar
for vs while
For si sabes N
While si depende de condición
for con índice
while sin índice
Trampas
menor vs menor igual
mayor vs mayor igual
Olvidar i++
i fuera de ámbito
length vs length
Tipos en múltiples variables
6.14.2 Las 12 ideas que no debes olvidar
- El
forclásico tiene tres partes: inicialización, condición, actualización. - La inicialización se ejecuta una sola vez; la condición se evalúa antes de cada iteración; la actualización se ejecuta después del cuerpo.
- El patrón estándar es
for (int i = 0; i < arr.length; i++). Es el 80 % de los casos. - Usa
<conlength, no<=. Es la trampa nº 1. - Al recorrer al revés, usa
i >= 0, noi > 0(para incluir el índice 0). - Puedes saltar con
i += k: de 2 en 2, de 3 en 3, etc. - Puedes usar múltiples variables:
for (int i = 0, j = n-1; i < j; i++, j--). Tienen que ser del mismo tipo. - La condición puede ser compleja:
i < n && !encontrado,i < n && arr[i] != 0, etc. - Las tres partes son opcionales, pero los dos
;son obligatorios.for (;;)es un bucle infinito. - Para Strings, usa
charAt(i)conforclásico (más eficiente quetoCharArray). ReservatoCharArraypara el for-each (sección 7). length(array, sin paréntesis) vslength()(String, con paréntesis). Memorízalo.forsi sabes cuántas iteraciones;whilesi depende de una condición. Es la regla de oro para elegir entre ambos.
6.14.3 Glosario rápido
| Término | Significado |
|---|---|
for clásico |
Bucle con inicialización, condición y actualización en una sola línea. |
| Inicialización | Primera parte del for: prepara variables (normalmente int i = 0). |
| Condición | Segunda parte: expresión booleana evaluada antes de cada iteración. |
| Actualización | Tercera parte: modifica variables después del cuerpo (normalmente i++). |
| Patrón estándar | for (int i = 0; i < arr.length; i++) — el caso más común. |
| Variante decreciente | for (int i = n - 1; i >= 0; i--) — recorrer al revés. |
| Variante con saltos | for (int i = 0; i < n; i += k) — saltar de k en k. |
| Múltiples variables | for (int i = 0, j = n - 1; ...; i++, j--) — dos índices en un solo for. |
for (;;) |
Bucle infinito equivalente a while (true). Suele combinarse con break. |
charAt(i) |
Método de String que devuelve el carácter en la posición i. |
length |
Campo de array (sin paréntesis): número de elementos. |
length() |
Método de String (con paréntesis): número de caracteres. |
| Arrays paralelos | Dos o más arrays cuyos elementos en la misma posición están relacionados. Mala práctica en POO (mejor una clase con varios campos). |
| Swap | Intercambio de dos valores usando una variable temp auxiliar. |
StringIndexOutOfBoundsException |
Excepción que lanza charAt(i) cuando i está fuera de rango. |
6.15 Actividades propuestas
Cinco actividades graduadas. Hazlas en orden. Las soluciones se publicarán en Aules.
6.15.1 Actividad 1 — Tabla de multiplicar completa
Objetivo: practicar el patrón estándar del for (sin array, solo iteración numérica).
Enunciado: Escribe un programa que pida al usuario un número N (entre 1 y 10) y muestre la tabla de multiplicar de N, del 1 al 10, con este formato:
Requisitos:
- Valida que
Nesté entre 1 y 10 conmatches. - Usa
for (int i = 1; i <= 10; i++). Fíjate que es<= 10, no< 10(no es un array, es una iteración numérica).
Entrega: archivo TablaMultiplicar.java en el paquete jams.programacion.ud3.
Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.
6.15.2 Actividad 2 — Invertir un array in-place
Objetivo: practicar múltiples variables y el patrón swap.
Enunciado: Dado un array de 8 enteros:
Imprime el array original, inviértelo in-place (sin crear un array nuevo) usando la técnica de i que avanza y j que retrocede con swap, y muestra el resultado. Ambas impresiones con Arrays.toString.
Requisitos:
- Usa
for (int i = 0, j = datos.length - 1; i < j; i++, j--). - Realiza el swap dentro del cuerpo con una variable
temp. - Importa
java.util.Arrays.
Entrega: archivo InvertirArray.java en el paquete jams.programacion.ud3.
Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.
6.15.3 Actividad 3 — Invertir un String
Objetivo: practicar la variante decreciente con charAt sobre Strings.
Enunciado: Pide al usuario una palabra y muestra su inverso (caracteres en orden inverso). Por ejemplo, "Hola" → "aloH".
Requisitos:
- Usa
for (int i = texto.length() - 1; i >= 0; i--). - Usa
texto.charAt(i)para acceder a cada carácter. - Construye el resultado concatenando con
+. - No uses
toCharArray()(esa es la alternativa que verás con for-each en la sección 7).
Entrega: archivo InvertirString.java en el paquete jams.programacion.ud3.
Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.
6.15.4 Actividad 4 — Comprobar palíndromo
Objetivo: practicar múltiples variables sobre Strings con charAt.
Enunciado: Pide al usuario una palabra y di si es palíndromo (se lee igual al derecho y al revés). Ignora mayúsculas con toLowerCase antes de comprobar. Ejemplos:
"reconocer"→ sí es palíndromo."Hola"→ no es palíndromo."Ana"→ sí es palíndromo (ignorando mayúsculas)."Radar"→ sí es palíndromo (ignorando mayúsculas).
Requisitos:
- Normaliza la entrada con
.trim().toLowerCase(). - Usa
for (int i = 0, j = texto.length() - 1; i < j; i++, j--). - Compara
texto.charAt(i) != texto.charAt(j). Si encuentras alguna diferencia, no es palíndromo. - Muestra "Es palíndromo" o "No es palíndromo".
Entrega: archivo Palindromo.java en el paquete jams.programacion.ud3.
Criterios evaluados: CE 3.2, CE 3.5, CE 3.7.
6.15.5 Actividad 5 — Cuestionario de repaso
Responde por escrito:
- ¿Cuáles son las tres partes del
forclásico y cuándo se ejecuta cada una? - Escribe el patrón estándar para recorrer un array de principio a fin.
- ¿Por qué se usa
<conlengthy no<=? - Escribe la variante decreciente para recorrer un array al revés.
- ¿Por qué en la variante decreciente se usa
i >= 0y noi > 0? - Escribe un
forque recorra posiciones pares de un array. - Escribe un
forcon múltiples variables para invertir un array. - ¿Puedes declarar varias variables de tipos distintos en la inicialización del
for? ¿Por qué? - ¿Qué es
for (;;)y para qué sirve? - ¿Cómo recorres los caracteres de un
Stringconforclásico sin crear un array nuevo? - ¿Cuál es la diferencia entre
lengthylength()? ¿Cuándo se usa cada uno? - ¿Cuándo eliges
fory cuándowhile? Pon un ejemplo de cada caso.
Entrega: archivo cuestionario_seccion6.md con tus respuestas.
Criterios evaluados: CE 3.2, CE 3.7.
6.16 Lo que NO hemos visto (y dónde verlo)
Esta sección te ha enseñado el for clásico en profundidad: desde el patrón estándar (que introduce el recorrido de arrays, que no se había visto en la sección 5) hasta todas sus variantes sobre arrays y Strings. Hay varias cosas relacionadas que se reservan para secciones/unidades posteriores:
| Concepto | ¿Por qué no aquí? | ¿Dónde se ve? |
|---|---|---|
for-each (recorrido sin índice) |
Bucle distinto al for clásico. |
Sección 7 de UD3. |
break y continue |
Sentencias de salto de bucle. | Sección 8 de UD3. |
break etiquetado |
Para salir de bucles anidados. | Sección 8 de UD3. |
| Bucles anidados (for dentro de for) | Combinación de bucles. | Sección 8 de UD3. |
Matrices bidimensionales int[][] |
Arrays de arrays. | Sección 8 de UD3. |
try-catch para manejar ArrayIndexOutOfBoundsException y StringIndexOutOfBoundsException |
Manejo de excepciones. | Sección 9 de UD3. |
StringBuilder para concatenación eficiente en bucles |
Clase del API Java. | UD2 (POO con la API de Java). |
| Streams API como alternativa a bucles | Forma declarativa de procesar colecciones. | UD6. |
Iterable<T> y colecciones (List, Set) |
Tipos avanzados de datos. | UD6. |
6.17 Lo que viene en la sección 7
Con esta sección ya dominas el for clásico en todas sus variantes sobre arrays y Strings. Pero hay un caso muy común en el que el for clásico es más verboso de lo necesario: cuando solo quieres recorrer todos los elementos en orden, sin necesidad de índice.
En la sección 7 verás el for-each (también llamado enhanced for), un bucle más simple y seguro para recorrer arrays sin índice:
Aprenderás:
- Sintaxis del
for-each:for (Tipo elemento : array) { ... }. - Cómo recorre todos los elementos sin índice.
- Cuándo usar for-each y cuándo for clásico (la regla: for-each lee, for clásico escribe).
- La limitación del for-each: no modifica el array (la variable es una copia).
- Recorrer caracteres de un
StringcontoCharArray()+ for-each.
Cuando termines la sección 7, tendrás las dos herramientas de recorrido completas: for clásico (con índice, para casos que lo necesitan) y for-each (sin índice, para recorrido simple). Después, en la sección 8 cerrarás el bloque de iteración con bucles anidados, matrices bidimensionales y sentencias de salto (break, continue, return).
Cierre del profesor. Llegar hasta aquí es mérito. Ya dominas el
forclásico en todas sus variantes: patrón estándar, decreciente, con saltos, múltiples variables, condición compleja, sobre Strings concharAt. Eso es el 80 % de lo que necesitas para recorrer arrays y strings en cualquier programa. La regla más importante que te llevas es<no<=conlength: el 90 % de los bugs conforvienen de usar<=. La segunda esforsi sabes cuántas iteraciones,whilesi no: elegir bien entre ambos hace tu código más legible. Nos vemos en la sección 7, donde verás elfor-eachcomo forma más simple y segura de recorrer arrays cuando no necesitas el índice. Es la última pieza del bloque de iteración simple antes de los bucles anidados.