Médio Java

Método genérico com bounded type

Enunciado

Escreva um método genérico maior que recebe uma lista de elementos que implementam Comparable<T> e retorna o maior elemento. O método deve ser public static <T extends Comparable<T>> T maior(List<T> lista). No main, teste com uma lista de Integer e uma de String, imprimindo o maior de cada.

Requisitos

  • O método deve ter a assinatura public static <T extends Comparable<T>> T maior(List<T> lista).
  • Deve lançar IllegalArgumentException se a lista estiver vazia.
  • O main deve testar com List<Integer> e List<String> e imprimir os resultados.

Código inicial

import java.util.List;

public class Main {
    public static void main(String[] args) {
        // TODO: testar maior com Integer e String
    }

    // TODO: implementar maior
}

Saída esperada

Maior Integer: 30
Maior String: banana
Ver dica

Use compareTo para comparar os elementos e inicialize o maior com o primeiro da lista.

Mostrar solução
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numeros = List.of(10, 30, 20);
        System.out.println("Maior Integer: " + maior(numeros));

        List<String> palavras = List.of("apple", "banana", "cherry");
        System.out.println("Maior String: " + maior(palavras));
    }

    public static <T extends Comparable<T>> T maior(List<T> lista) {
        if (lista.isEmpty()) {
            throw new IllegalArgumentException("Lista vazia");
        }
        T max = lista.get(0);
        for (T item : lista) {
            if (item.compareTo(max) > 0) {
                max = item;
            }
        }
        return max;
    }
}

Passo a passo

  1. O método maior é genérico e declara <T extends Comparable<T>> para garantir que os elementos podem ser comparados entre si.
  2. Verificamos se a lista está vazia e lançamos IllegalArgumentException para evitar erros.
  3. Inicializamos max com o primeiro elemento da lista.
  4. Percorremos a lista e usamos compareTo para verificar se o item atual é maior que max.
  5. Se for, atualizamos max.
  6. Ao final, retornamos max.
  7. No main, chamamos maior com List<Integer> e List<String>, e a inferência de tipo funciona automaticamente.

Por que funciona

O bounded type <T extends Comparable<T>> permite que o compilador saiba que T tem o método compareTo, então podemos usá-lo sem casts. Isso é um exemplo clássico de genéricos com restrição, muito usado em algoritmos de ordenação e busca. A type erasure remove a informação de tipo em runtime, mas a verificação em compile-time garante segurança.

Erros comuns

  • Esquecer o bound: public static <T> T maior(List<T> lista) causaria erro de compilação ao chamar compareTo.
  • Usar > em vez de compareTo: if (item > max) não compila para tipos genéricos.
  • Não tratar lista vazia: lista.get(0) lançaria IndexOutOfBoundsException.
  • Declarar T extends Comparable sem o parâmetro: Comparable é raw type e gera warning.

Outra forma de resolver

Usar Collections.max(lista), que já implementa essa lógica, mas requer que a lista seja não vazia e os elementos sejam Comparable. É preferível para produção, mas o exercício pede a implementação manual.

Saída esperada

Maior Integer: 30
Maior String: banana