Em Java, os mapas representam estruturas de dados que associam chaves a valores, permitindo armazenar, acessar, atualizar e remover pares chave-valor de forma eficiente. Ao contrário das coleções que armazenam apenas elementos, os mapas mantêm uma relação de mapeamento, em que cada chave é única e aponta para exatamente um valor, embora os valores possam se repetir.

A interface Map possui mecanismos para a obtenção de valores a partir de chaves únicas (não duplicadas). A interface Map fornece três visões de coleções que permitem que o conteúdo do mapa seja manipulado de diferentes formas: um conjunto de chaves, uma coleção de valores ou um conjunto de mapeamentos entre chaves e valores. A principal interface derivada de Map é SortedMap, que representa mapas ordenados, e sua subinterface NavigableMap. Map é amplamente usada pelas classes da biblioteca padrão da linguagem. As principais classes que implementam a interface Map para mapas não concorrentes são HashMap, LinkedHashMap e TreeMap. Para mapas concorrentes, destacam-se ConcurrentHashMap e ConcurrentSkipListMap.

A seguir, temos parte da definição da interface Map, contendo apenas os principais métodos:

public interface Map<K,V>{
    // Operações de Consulta
    int size();
    boolean isEmpty();
    boolean containsKey(Object key);
    boolean containsValue(Object value);
    V get(Object key);

    // Operações de modificação
    V put(K key, V value);
    V remove(Object key);
    void putAll(Map<? extends K, ? extends V> m);
    void clear();

    // Visões
    Set<K> keySet();
    Collection<V> values();
    Set<Map.Entry<K, V>> entrySet();

    // Definição da interface Entry
    interface Entry<K, V> {
        // Corpo omitido
    }

    // (continua...)
}

O exemplo a seguir mostra um mapa de carros contendo como chaves as placas e como valores os nomes dos modelos dos respectivos carros. Com esse mapa, podemos, por exemplo, testar a existência de um dado elemento usando o valor da chave como parâmetro para o método containsKey. Além disso, o método get obtém o valor a partir da chave passada como parâmetro e o método remove exclui o valor do mapa:

void main() {
    Map<String, String> carros = new HashMap<>();
    carros.put("ABCD2935", "Tesla Model S");
    carros.put("YJKF9353", "Toyota Corolla");
    carros.put("WFLO1304", "Honda CRV");

    var key = "ABCD2935";

    if (carros.containsKey(key)){
        IO.println("Dados - veículo:");
        IO.println(carros.get(key));
        IO.println("Removendo o veículo...");
        carros.remove(key);
    } else
        IO.println("Veículo não encontrado!");
}

A saída seria:

Dados - veículo:
Tesla Model S
Removendo o veículo...

Além dos métodos descritos acima, temos ainda diversos métodos padrão (default), que implementam funcionalidades adicionais.

A interface disponibiliza ainda métodos para a criação de mapas imutáveis a partir de valores fornecidos (métodos of e ofEntries, e ainda o método auxiliar entry) ou a partir de um mapa existente (copyOf).

A Figura 1 mostra a interface Map e suas principais subinterfaces. As subinterfaces diretas de Map são SequencedMap, Bindings e ConcurrentMap. Indiretamente, são ainda interfaces de Map as interfaces SortedMap, NavigableMap e ConcurrentNavigableMap (esta também é subinterface de ConcurrentMap).

Interface Map e suas subinterfaces

Dentre as mais importantes descendentes de Map estão as interfaces SortedMap e NavigableMap.

A interface SortedMap é uma extensão da interface SequencedMap que representa mapas que mantêm as chaves em uma ordem específica, de acordo com a ordem natural das chaves ou com um comparador específico fornecido durante a criação do mapa. Sua única subinterface direta na biblioteca de coleções, NavigableMap, adiciona métodos que fornecem operações de navegação mais avançadas para manipulação das chaves do mapa, tais como obter a chave mais próxima de um valor específico ou iterar sobre o mapa em ordem crescente ou decrescente.

Comumente, usamos NavigableMap em vez de SortedMap, pois ambas as classes que implementam SortedMap no framework de coleções o fazem indiretamente (TreeMap implementa NavigableMap, e ConcurrentSkipListMap implementa ConcurrentNavigableMap). Já NavigableMap vai um pouco além em termos de funcionalidades, fornecendo alguns métodos específicos para navegação no mapa, de maneira análoga ao que NavigableSet fornece para conjuntos.


Este artigo é uma adaptação de conteúdo do livro Orientação a Objetos com Java, de Eduardo Kessler Piveta