1. Busca de elementos em coleções
Busca com métodos padrão
Quando temos uma lista, por exemplo, de nomes:
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
O Java oferece alguns métodos práticos para busca:
- contains(Object o) — verifica se o elemento está na coleção.
- indexOf(Object o) — retorna o primeiro índice de ocorrência do elemento (ou -1, se não encontrado).
- lastIndexOf(Object o) — retorna o último índice de ocorrência do elemento (ou -1).
Exemplos:
System.out.println(names.contains("Anna")); // true
System.out.println(names.indexOf("Anna")); // 0
System.out.println(names.lastIndexOf("Anna")); // 3
System.out.println(names.contains("Sergey")); // false
Fato: Para coleções do tipo Set não existem os métodos indexOf e lastIndexOf — em Set não há índices, apenas valores únicos.
Busca por condição
Às vezes, é preciso encontrar não um valor específico, mas um elemento que atenda a uma condição. Por exemplo, encontrar o primeiro nome com mais de 6 caracteres. Um laço for comum funciona muito bem: assim que encontrar um elemento adequado — use break.
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
String found = null;
for (String name : names) {
if (name.length() > 6) {
found = name;
break; // Encontramos o primeiro correspondente; podemos sair do laço
}
}
System.out.println(found); // Viktoriya
Busca do valor máximo e mínimo
Para coleções com elementos comparáveis (por exemplo, números), é possível encontrar rapidamente o máximo e o mínimo com a classe Collections.
List<Integer> numbers = List.of(10, 5, 20, 7, 20, 3);
int max = Collections.max(numbers); // 20
int min = Collections.min(numbers); // 3
System.out.println("Máximo: " + max);
System.out.println("Mínimo: " + min);
Importante: os elementos devem ser comparáveis (implementar Comparable); caso contrário, será necessário fornecer um comparador.
2. Ordenação de coleções
Ordenação padrão de lista
É possível ordenar apenas listas mutáveis (por exemplo, ArrayList, LinkedList). Coleções do tipo Set e Map não suportam ordenação diretamente.
Por padrão, a ordenação segue a “ordem natural”: para números — crescente; para strings — alfabética.
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]
É possível fazer o mesmo pelo método da lista sort:
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null significa: usar a ordem natural
System.out.println(numbers); // [1, 3, 5, 7]
Ordenação com Comparator
Se você precisa de sua própria regra — por exemplo, ordenar strings pelo comprimento:
List<String> words = new ArrayList<>(List.of("gato", "elefante", "mosca", "rinoceronte"));
words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [gato, mosca, elefante, rinoceronte]
Em ordem inversa:
words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [rinoceronte, elefante, mosca, gato]
Estilo antigo com Collections.sort:
Collections.sort(words, Comparator.comparingInt(String::length));
3. Particularidades da ordenação de diferentes coleções
A ordenação altera apenas listas
Os métodos de ordenação (sort, Collections.sort) funcionam somente com coleções que mantêm ordem dos elementos (por exemplo, List). Para Set e Map tais métodos não são previstos.
Tentativa de ordenar um Set:
Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // Erro de compilação: sort espera um List!
Se você precisa obter uma lista ordenada a partir de Set:
List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]
Ordenação de Map: por chaves e por valores
Não é possível ordenar Map diretamente, mas você pode:
- Obter uma lista de pares “chave–valor”
- Ordená-la da forma desejada
- Se necessário, montar um novo Map
Exemplo: ordenação por valores
Map<String, Integer> scores = Map.of(
"Anna", 15,
"Boris", 20,
"Vika", 12
);
List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Vika: 12
// Anna: 15
// Boris: 20
Ordenando objetos por um campo
Suponha que temos uma classe de usuário:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
E uma lista de usuários:
List<User> users = new ArrayList<>(List.of(
new User("Anna", 22),
new User("Boris", 18),
new User("Vika", 25)
));
Ordenando por idade:
users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [Boris (18), Anna (22), Vika (25)]
Em ordem inversa:
users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [Vika (25), Anna (22), Boris (18)]
4. Erros comuns ao buscar e ordenar coleções
Erro nº 1: ordenar uma lista imutável. Listas criadas com List.of(...) não podem ser modificadas — ao chamar sort você receberá UnsupportedOperationException.
List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // Lançará uma exceção!
Erro nº 2: ordenar Set ou Map diretamente. Os métodos de ordenação não funcionam com Set e Map. Se precisar ordenar, primeiro transforme os dados em uma lista.
Erro nº 3: comparação incorreta de objetos. Não subtraia inteiros “na marra” ao comparar — pode ocorrer overflow. Em vez de u1.age - u2.age use Integer.compare ou Comparator.comparingInt.
// users.sort((u1, u2) -> u1.age - u2.age); // Funciona, mas é perigoso por causa de overflow!
Erro nº 4: usar contains para buscas complexas. O método contains verifica apenas correspondência exata (via equals). Se for preciso procurar por parte da string ou por um campo do objeto — use um laço com verificação de condição ou comparadores/streams.
GO TO FULL VERSION