String es una clase inmutable. Cualquier modificación sobre un objeto String crea un nuevo espacio en memoria. Ejemplo:
String texto = "Hola Mundo";
char[] arrChars = {'X', 'Y', 'Z'};
String desdeArr = new String(arrChars);
// Recorrido
for (int i = 0; i < texto.length(); i++)
System.out.print(texto.charAt(i));
System.out.println();
for (char c : texto.toCharArray())
System.out.print(c);
System.out.println();
// Métodos comunes
texto.charAt(0); // 'H'
texto.compareTo("G"); // 1
texto.equals("Hola Mundo"); // true
texto.startsWith("Ho"); // true
texto.endsWith("do"); // true
texto.indexOf('o'); // 1
texto.indexOf('o', 3); // 4
texto.lastIndexOf('o'); // 4
texto.replace('o', 'a'); // "Hala Munda"
texto.split(" "); // ["Hola", "Mundo"]
texto.substring(0, 4); // "Hola"
texto.toLowerCase(); // "hola mundo"
texto.toUpperCase(); // "HOLA MUNDO"
Para modificacionse frecuentes se usan StringBuilder (más rápido, no sincronizado) o StringBuffer (hilo seguro). Ejemplo con StringBuilder:
StringBuilder sb = new StringBuilder("Hola");
sb.append(" Mundo"); // "Hola Mundo"
sb.reverse(); // "odnuM aloH"
sb.delete(0, 5); // "aloH"
sb.insert(2, "X"); // "alXoH"
sb.replace(0, 2, "AB"); // "ABXoH"
String resultado = sb.toString(); // "ABXoH"
- Arrays
La clase java.util.Arrays ofrece métodos estáticos para manipular arreglso:
int[] nums = {5, 2, 4, 1, 3};
int[][] mat = {{1,2},{3,4}};
// Ordenar
Arrays.sort(nums); // [1,2,3,4,5]
Integer[] numsW = {5,2,4,1,3};
Arrays.sort(numsW, (a,b) -> b - a); // [5,4,3,2,1]
// Búsqueda binaria (requiere arreglo ordenado)
int pos = Arrays.binarySearch(nums, 3); // 2
// Comparación
boolean iguales = Arrays.equals(nums, nums);
// Rellenar
Arrays.fill(nums, 0); // [0,0,0,0,0]
// Convertir a String
String str1 = Arrays.toString(nums); // "[0,0,0,0,0]"
String str2 = Arrays.deepToString(mat); // "[[1,2],[3,4]]"
- ArrayList
ArrayList es una implementación dinámica de List basada en arreglo. Declaración y uso:
import java.util.*;
ArrayList<Integer> lista = new ArrayList<>();
ArrayList<Integer> lista2 = new ArrayList<>(Arrays.asList(1,2,3));
// Recorridos
for (int i = 0; i < lista2.size(); i++)
System.out.print(lista2.get(i));
for (int x : lista2) System.out.print(x);
Iterator<Integer> it = lista2.iterator();
while (it.hasNext()) System.out.print(it.next());
lista2.stream().forEach(x -> System.out.print(x));
// Métodos comunes
lista2.add(4); // [1,2,3,4]
lista2.add(1, 5); // [1,5,2,3,4]
lista2.remove(Integer.valueOf(3)); // elimina el objeto 3
lista2.set(0, 9); // [9,5,2,4]
lista2.subList(0, 2); // [9,5]
lista2.indexOf(5); // 1
lista2.isEmpty(); // false
lista2.contains(2); // true
lista2.sort(Comparator.naturalOrder()); // [2,4,5,9]
lista2.sort(Comparator.reverseOrder()); // [9,5,4,2]
lista2.addAll(Arrays.asList(10,20)); // [9,5,4,2,10,20]
Collections.addAll(lista2, 30,40); // [9,5,4,2,10,20,30,40]
Collections.reverse(lista2); // [40,30,20,10,2,4,5,9]
// Convertir a arreglo
Integer[] arr = lista2.toArray(new Integer[0]);
int[] primitivos = lista2.stream().mapToInt(Integer::intValue).toArray();
- LinkedList
LinkedList implementa List y Deque como lista doblemente enlazada. Eficiente para inserciones/eliminaciones en cualquier posición. Métodos adicionales:
LinkedList<Integer>> enlazada = new LinkedList<>(Arrays.asList(1,2,3));
enlazada.addLast(4); // [1,2,3,4]
enlazada.addFirst(5); // [5,1,2,3,4]
enlazada.removeLast(); // elimina 4 → [5,1,2,3]
enlazada.removeFirst(); // elimina 5 → [1,2,3]
enlazada.getFirst(); // 1
enlazada.getLast(); // 3
- HashSet / TreeSet
HashSet es un conjunto sin orden ni duplicados, basado en HashMap. TreeSet mantiene orden natural.
HashSet<Integer> conjunto = new HashSet<>(Arrays.asList(3,1,2,1));
// conjunto = {1,2,3}
conjunto.add(4); // {1,2,3,4}
conjunto.remove(2); // {1,3,4}
conjunto.contains(3); // true
conjunto.size(); // 3
TreeSet<Integer> ordSet = new TreeSet<>(Arrays.asList(5,2,4,2));
// ordSet = {2,4,5}
ordSet.ceiling(3); // 4 (mayor o igual)
ordSet.floor(3); // 2 (menor o igual)
- HashMap / TreeMap
HashMap almacena pares clave-valor sin orden. TreeMap ordena por clave ascendente.
HashMap<String, Integer> mapa = new HashMap<>();
mapa.put("A", 10);
mapa.put("B", 20);
mapa.put("A", 30); // sobrescribe
// Recorridos
for (String k : mapa.keySet()) System.out.println(k);
for (int v : mapa.values()) System.out.println(v);
for (Map.Entry<String,Integer> e : mapa.entrySet())
System.out.println(e.getKey()+" "+e.getValue());
// Métodos
mapa.get("A"); // 30
mapa.remove("B"); // elimina B
mapa.containsKey("A"); // true
mapa.containsValue(30); // true
// TreeMap
TreeMap<String,Integer> tMap = new TreeMap<>();
tMap.put("Z", 1);
tMap.put("A", 2);
tMap.ceilingKey("B"); // "Z" (clave mínima >= "B")
tMap.floorKey("B"); // "A" (clave máxima <= "B")
- Stack
Se recomienda usar ArrayDeque como pila en lugar de la vieja clase Stack:
Deque<String> pila = new ArrayDeque<>();
pila.push("primero");
pila.push("segundo");
pila.push("tercero");
while (!pila.isEmpty())
System.out.print(pila.pop() + " "); // tercero segundo primero
- Queue / PriorityQueue
LinkedList implementa Queue (FIFO). PriorityQueue ordena por prioridad.
Queue<Integer> cola = new LinkedList<>();
cola.offer(10); cola.offer(20); cola.offer(30);
while (cola.peek() != null)
System.out.print(cola.poll() + " "); // 10 20 30
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.offer(5); pq.offer(1); pq.offer(3);
while (!pq.isEmpty())
System.out.print(pq.poll() + " "); // 1 3 5
// Orden inverso
PriorityQueue<Integer> pqInv = new PriorityQueue<>(Collections.reverseOrder());
pqInv.addAll(Arrays.asList(5,1,3));
while (!pqInv.isEmpty())
System.out.print(pqInv.poll() + " "); // 5 3 1
- Iterator y Collection
La interfaz Collection es la raíz de todas las colecciones. Permite escribir código genérico:
public static void mostrar(Iterator<?> it) {
while (it.hasNext())
System.out.print(it.next() + " ");
}
public static void mostrar(Collection<?> col) {
for (Object o : col)
System.out.print(o + " ");
}
// Uso
List<Integer> l = Arrays.asList(1,2,2);
Set<Integer> s = new HashSet<>(Arrays.asList(1,2,2));
mostrar(l.iterator()); // 1 2 2
mostrar(s.iterator()); // 1 2
mostrar(l); // 1 2 2
mostrar(s); // 1 2
- Ordenación de arreglos de objetos personalizados
Implementar Comparable<T> y sobrescribir compareTo:
class Dato implements Comparable<Dato> {
int id;
String nombre;
Dato(int id, String nombre) {
this.id = id;
this.nombre = nombre;
}
@Override
public int compareTo(Dato otro) {
return otro.id - this.id; // orden descendente por id
}
@Override
public String toString() {
return "[" + id + ", " + nombre + "]";
}
}
Dato[] datos = {new Dato(3, "Ana"), new Dato(1, "Luis"), new Dato(2, "Pedro")};
Arrays.sort(datos);
System.out.println(Arrays.toString(datos)); // [3, Ana] [2, Pedro] [1, Luis]