Olá! Hoje falaremos sobre outra estrutura de dados – Mapa. Seu nome oficial em russo é “matriz associativa”, mas não é usado com frequência. As opções mais comuns são “dicionário”, “mapa” ou (na maioria das vezes) a gíria anglicística “mapa” :) Dentro do Mapa, os dados são armazenados no formato “chave” - “valor”, ou seja, em pares. Tanto as chaves quanto os valores podem ser quaisquer objetos – números, strings ou objetos de outras classes.
Como o Map difere de outras estruturas de dados
Anteriormente, examinamos estruturas de dados onde os elementos são armazenados sozinhos. Em um array, ou ArrayList / LinkedList , armazenamos um determinado número de elementos. Mas e se nossa tarefa mudar um pouco? Por exemplo, imagine que nos deparamos com a tarefa de criar uma lista de 100 pessoas, onde serão armazenados o nome completo e o número do passaporte da pessoa. Em princípio, não é tão difícil. Por exemplo, você pode encaixar ambos em uma linha e criar uma lista de linhas como esta: “Anna Ivanovna Reshetnikova, 4211 717171”. Mas esta solução tem duas desvantagens. Primeiro, podemos precisar de uma função de busca de passaporte. E com esse formato de armazenamento de informações, isso será problemático. E em segundo lugar, nada nos impedirá de criar duas pessoas diferentes com os mesmos números de passaporte. E esta é a desvantagem mais séria da nossa solução. Tais situações devem ser totalmente excluídas, não existem duas pessoas com o mesmo número de passaporte. Aqui o Mapa e seus recursos declarados vêm em nosso auxílio (armazenando dados em um par no formato “chave”-”valor”). Vejamos a implementação de mapa mais comum - a classe Java HashMap .Criando um HashMap em Java e trabalhando com a classe
Esta implementação é muito simples de criar:public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
}
Aqui criamos um dicionário no qual os elementos serão armazenados no formato “string numérica”. O número será a chave e a string será o valor. Também indicamos que tipo de chaves teremos ( Integer
) e que tipo de valores teremos ( String
). Porque isto é assim? Primeiro, a chave em um HashMap é sempre única . Isso funcionará muito bem para nós porque podemos usar o número do passaporte como chave e evitar duplicatas. E a linha com o nome completo funcionará como um valor (o nome completo de pessoas diferentes pode ser facilmente repetido, não há nada de errado com isso para nós).
Adicionando um novo par a um HashMap
Esta tarefa é semelhante a esta:public class Main {
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
System.out.println(passportsAndNames);
}
}
O método é usado para isso put()
. Além disso, HashMap possui um método substituído toString()
para que possa ser impresso no console. A saída será semelhante a esta: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebryakov}
Recursos das chaves HashMap
Agora vamos verificar se as chaves são verdadeiramente únicas? Vamos tentar adicionar um novo elemento com uma chave já presente no mapa:public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
passportsAndNames.put(162348, "Viktor Mikhailovich Stychkin");//repeat key
System.out.println(passportsAndNames);
}
Saída: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Viktor Mikhailovich Stychkin} O elemento anterior com chave 162348, como você pode ver, foi substituído. “A Chave” foi chamada de chave por um motivo. Os valores em um HashMap são acessados por chave (mas não vice-versa - a chave não pode ser obtida por valor, pois os valores podem ser duplicados). Isso é visto claramente nos exemplos de obtenção de um elemento, bem como de remoção de um elemento de um HashMap:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
String lidiaName = passportsAndNames.get(212133);
System.out.println(lidiaName);
passportsAndNames.remove(162348);
System.out.println(passportsAndNames);
}
Para obter um valor ou remover um par do dicionário, devemos passar aos get()
métodos remove()
exatamente a chave única correspondente a esse valor . Não existem índices numéricos, como em arrays ou listas, no HashMap – o valor é acessado por chave. Saída do console: Lidiya Arkadyevna Bublikova {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump}
Verificando a presença de uma chave e um valor
Nas classes ArrayList e LinkedList , poderíamos verificar se uma lista contém um determinado elemento. HashMap também permite fazer isso, e para ambas as partes do par: possui métodoscontainsKey()
(verifica a presença de uma chave) e containsValue()
(verifica a presença de um valor).
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
System.out.println(passportsAndNames.containsKey(11111));
System.out.println(passportsAndNames.containsValue("Donald John Trump"));
}
Saída: falso verdadeiro
Obtendo uma lista de todas as chaves e valores
Outro recurso conveniente do HashMap é que você pode obter separadamente uma lista de todas as chaves e todos os valores . Para isso, são utilizados métodoskeySet()
e values()
:
public class Main {
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
Set<Integer> keys = passportsAndNames.keySet();
System.out.println("Keys: " + keys);
ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
System.out.println("Values: " + values);
}
}
As chaves são extraídas para a coleção Set
. Sua peculiaridade é que não pode conter elementos repetidos. Agora, a principal coisa a lembrar é que a lista de todas as chaves pode ser retirada do HashMap e colocada em uma coleção separada. No exemplo, salvamos os valores normais ArrayList
. Saída do console: Chaves: [212133, 8082771, 162348] Valores: [Lidiya Arkadyevna Bublikova, Donald John Trump, Ivan Mikhailovich Serebryakov] Os métodos size()
fazem clear()
exatamente a mesma coisa que nas estruturas anteriores pelas quais passamos: o primeiro retorna um número de elementos no dicionário no momento atual, o segundo exclui todos os elementos.
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
System.out.println(passportsAndNames.size());
passportsAndNames.clear();
System.out.println(passportsAndNames);
}
Saída: 3 {} Para verificar se nosso HashMap possui pelo menos um elemento, podemos usar o método isEmpty()
:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
if (!passportsAndNames.isEmpty()) {
System.out.println(passportsAndNames);
}
}
Saída: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebryakov} Agora enviaremos para o console somente após verificação preliminar :)
Combinando dois mapas em um
Outro ponto interessante é que dois mapas podem ser combinados em um só . Existe um método para issoputAll()
. Chamamos isso no primeiro HashMap , passamos o segundo como argumento e os elementos do segundo serão adicionados ao primeiro:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
HashMap<Integer, String> passportsAndNames2 = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
passportsAndNames2.put(917352, "Alexey Andreevich Ermakov");
passportsAndNames2.put(925648, "Maxim Olegovich Arkharov");
passportsAndNames.putAll(passportsAndNames2);
System.out.println(passportsAndNames);
}
Saída: {917352=Alexey Andreevich Ermakov, 212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 925648=Maxim Olegovich Arkharov, 162348=Ivan Mikhailovich Serebryakov} Todos os elementos de passaportesAndNames2 foram copiados para passaportesAndNames . Agora vamos ver um exemplo mais complicado. Ou seja, itere sobre HashMap em um loop.
for (Map.Entry entry: passportsAndNames.entrySet()) {
System.out.println(entry);
}
Uma interface Map.Entry
significa apenas um par chave-valor dentro de um dicionário. O método entrySet()
retorna uma lista de todos os pares em nosso HashMap (já que nosso mapa consiste exatamente nesses pares de entrada, iteramos sobre pares, e não sobre chaves ou valores separadamente). Conclusão: 212133=Lidiya Arkadyevna Bublikova 8082771=Donald John Trump 162348=Ivan Mikhailovich Serebryakov Guarde este artigo para o futuro: https://habr.com/ru/post/128017/ Agora é muito cedo para lê-lo, mas no futuro , quando você começar a usar o HashMap, ele o ajudará a entender como essa estrutura de dados funciona por dentro. Além disso, não se esqueça de verificar a documentação oficial da Oracle no HashMap.
GO TO FULL VERSION