- Aprender
- Computação e TI
- Programação
- Programação orientada a objetos com Java
- HashMaps e coleções em Java
HashMaps e coleções em Java
HashMap, contar e agrupar valores e manter valores únicos com HashSet. Conheça as garantias das interfaces List, Set e Map, ordene listas, defina uma ordem natural para suas próprias classes com Comparable e escolha a coleção adequada para cada tarefa.BásicoAula 7 de 11 do curso Curso de Programação orientada a objetos com Java
O que você vai aprender
- Crie mapas de dispersão, adicione, leia, atualize e remova pares chave–valor, percorra o conteúdo de um mapa e use suas próprias classes como chaves que o mapa possa encontrar novamente.
- Crie um HashMap e insira, consulte, atualize e remova entradasDeclare um HashMap com seus tipos de chave e de valor, armazene pares com put, leia-os com get e trate chaves ausentes.
- Percorra chaves, valores e entradasPercorra todos os pares de um mapa com keySet, values e entrySet, saiba qual ordem esperar e altere um mapa com segurança durante o percurso.
- Use seus próprios objetos como chaves de mapasFaça objetos de suas próprias classes funcionarem como chaves, sobrescrevendo equals e hashCode em conjunto, e mantenha as chaves inalteradas enquanto estiverem em um mapa.
- Crie um HashMap e insira, consulte, atualize e remova entradas
- Use mapas para contar a frequência de ocorrências, reunir valores relacionados sob uma mesma chave e construir tabelas de consulta que encontrem objetos rapidamente.
- Conte ocorrências e acumule totais por chaveConstrua tabelas de frequências e somas acumuladas com o padrão getOrDefault e interprete os resultados corretamente.
- Agrupe valores sob uma mesma chave usando listas e conjuntos como valoresConstrua mapas cujos valores sejam listas ou conjuntos, adicione itens ao grupo correto e evite erros que façam grupos se perderem ou deixarem de funcionar.
- Consulte objetos e preços rapidamente com um índice baseado em mapaUse mapas como tabelas de consulta e índices que encontram objetos por uma chave única, mantenha-os dentro de uma classe e mantenha vários índices consistentes.
- Conte ocorrências e acumule totais por chave
- Use HashSet para armazenar valores sem duplicatas, testar a pertinência rapidamente e combinar conjuntos por união, interseção e diferença.
- Armazene valores únicos e teste a pertinência com HashSetAdicione, verifique e remova valores em um HashSet, use o resultado de add e remova duplicatas de uma lista.
- Combine conjuntos e mantenha sua ordemCalcule uniões, interseções e diferenças sem alterar os conjuntos originais, compare conjuntos e escolha um conjunto ordenado quando a ordem importar.
- Armazene valores únicos e teste a pertinência com HashSet
- Declare coleções por seus tipos de interface, conheça as garantias de cada interface e use os métodos comuns que funcionam nas diferentes implementações.
- Declare variáveis e parâmetros com tipos de interfaceExplique o que é um tipo de interface, declare coleções como List, Set ou Map e escreva métodos que aceitem qualquer implementação.
- Conheça as garantias de List, Set e MapCompare as garantias das três interfaces, reconheça suas principais implementações e trabalhe com coleções não modificáveis criadas com of.
- Declare variáveis e parâmetros com tipos de interface
- Ordene listas em ordem natural, defina uma ordem natural para suas próprias classes implementando Comparable e use essa ordem em conjuntos e mapas ordenados.
- Ordene listas de números e cadeias de caracteresOrdene uma lista na própria lista com Collections.sort, preveja a ordem de cadeias de caracteres e ordene em ordem inversa ou sem distinguir maiúsculas de minúsculas.
- Implemente Comparable em sua própria classeDefina uma ordem natural para uma classe implementando Comparable e escrevendo compareTo com comparações seguras de números e cadeias de caracteres.
- Resolva empates e use conjuntos e mapas ordenadosOrdene objetos por vários campos, mantenha compareTo consistente com equals e use TreeSet e TreeMap para manter dados ordenados.
- Ordene listas de números e cadeias de caracteres
- Compare a velocidade das operações comuns em cada coleção e escolha o tipo adequado ao que o programa precisa fazer com seus dados.
- Compare o custo de operações comuns em coleçõesEstime como o tempo de consultas, inserções e remoções cresce com o tamanho de cada coleção e identifique padrões lentos.
- Selecione uma coleção que atenda à tarefaResponda a algumas perguntas sobre ordem, duplicatas e consultas para escolher entre vetores, listas, conjuntos e mapas, e combine-os para dados mais complexos.
- Compare o custo de operações comuns em coleções
Guia de estudo de HashMaps e coleções em Java
1Armazene e consulte dados por chave com HashMap
Um código de produto pode levar diretamente a uma quantidade em estoque, sem pesquisar uma lista. Mapas tornam essa associação explícita, mas usá-los bem também exige tratar chaves ausentes, visitar pares com segurança e definir quando dois objetos usados como chaves são considerados iguais. Comece com um pequeno mapa de estoque e acompanhe como seu conteúdo muda e como Java encontra novamente uma chave armazenada. As mesmas regras de igualdade serão importantes quando você usar conjuntos.
1.1 Crie um HashMap e insira, consulte, atualize e remova entradas
Um mapa armazena uma associação de cada chave a um valor. Em um mapa de estoque, o nome de um produto é a chave e sua quantidade é o valor. Dois produtos podem ter a mesma quantidade, mas uma chave de produto não pode ter duas entradas separadas.
Crie o mapa
import java.util.HashMap;
HashMap<String, Integer> stock = new HashMap<>();
O primeiro tipo, String, descreve as chaves. O segundo, Integer, descreve os valores. O diamante <> à direita permite que Java infira esses tipos. Os argumentos de tipo devem ser tipos de referência: use Integer, Double, Character ou Boolean em vez de int, double, char ou boolean. Java empacota um int simples quando o armazena como Integer e desempacota um Integer quando um int é necessário.
Acompanhe cada alteração
stock.put("apple", 12);
stock.put("pear", 7);
Integer previous = stock.put("apple", 15);
A primeira chamada cria apple=12; a segunda adiciona pear=7. A terceira encontra a chave existente "apple" e substitui seu valor. O mapa agora tem duas entradas, e previous contém 12. Um put para uma chave sem associação anterior retorna null.
stock.get("apple") agora retorna 15. stock.remove("pear") retorna 7 e remove essa entrada. Remover "pear" novamente retorna null. size() conta as entradas, isEmpty() verifica se não há nenhuma e clear() remove todas as entradas.
Trate uma chave ausente
stock.get("kiwi") retorna null, e stock.containsKey("kiwi") retorna false. Esta instrução compila, mas falha quando é executada:
int quantity = stock.get("kiwi");
Java tenta desempacotar null em um int, causando uma NullPointerException. Para um mapa de quantidades não nulas, use um valor padrão:
int quantity = stock.getOrDefault("kiwi", 0);
Isso fornece 0 sem adicionar "kiwi" ao mapa. Você também pode verificar containsKey antes da leitura. containsValue(15) verifica se alguma entrada tem esse valor; ele pode percorrer todos os valores, portanto é diferente de encontrar uma chave conhecida.
Um HashMap também permite uma chave null e valores null. Se uma chave estiver explicitamente associada a null, getOrDefault retornará o null armazenado, não o valor padrão. containsKey distingue esse caso de uma chave ausente. Mapas de quantidades são mais simples quando cada quantidade armazenada é um número real.
Faça a correspondência correta de chaves e valores
Chaves do tipo String distinguem maiúsculas de minúsculas: "apple", "Apple" e "apple " são diferentes. Aplique a mesma limpeza antes de armazenar e pesquisar, por exemplo, name.trim().toLowerCase(). Limpar apenas uma chave de pesquisa não corrige chaves armazenadas de forma inconsistente.
Compare valores empacotados pelo conteúdo com equals. Se duas entradas contiverem 1000, suas referências Integer podem ser diferentes, portanto == pode ser falso mesmo que seus conteúdos numéricos correspondam. Depois de verificar que ambos os valores são não nulos, a.equals(b) compara seus conteúdos.
Principais conclusões
- Cada chave única está associada a um valor; valores podem se repetir.
putsubstitui um valor existente e retorna o valor anterior.- Uma chamada a
getpara uma chave ausente retornanull; desempacotá-lo causa umaNullPointerException. getOrDefaultfornece um valor padrão somente para uma chave ausente.- Faça a correspondência de chaves de texto de forma consistente e compare valores empacotados pelo conteúdo.
1.2 Percorra chaves, valores e entradas
Um mapa pode responder a uma única consulta ou fornecer todos os seus dados a um laço. Escolha a visão que fornece as partes necessárias ao laço. As visões estão vinculadas ao mapa, portanto alterações feitas por meio delas também podem alterar o mapa.
Escolha chaves, valores ou entradas
Use keySet() para visitar as chaves. Uma consulta dentro desse laço pode recuperar cada valor:
for (String name : phoneBook.keySet()) {
System.out.println(name + ": " + phoneBook.get(name));
}
Use values() quando as chaves não forem relevantes. Para as quantidades em estoque maçã 15, pera 7 e figo 3:
int total = 0;
for (int quantity : stock.values()) {
total += quantity;
}
O total passa a ser 25. Valores repetidos ainda contribuem separadamente: uma visão de valores não é um conjunto.
Uma entrada contém uma chave e seu valor juntos. Importe java.util.Map e use Map.Entry<K, V> com getKey() e getValue(). Isso evita uma segunda consulta:
String best = null;
int bestScore = Integer.MIN_VALUE;
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
if (best == null || entry.getValue() > bestScore) {
best = entry.getKey();
bestScore = entry.getValue();
}
}
Para Ana 82, Ben 91 e Cai 77, o resultado é Ben com 91. O teste best == null também trata uma primeira pontuação igual ao menor valor possível de int. Um mapa vazio deixa best como null.
Escolha a ordem explicitamente
Um HashMap não garante uma ordem de iteração. Não se pode presumir a ordem de inserção, a ordem classificada ou a ordem exibida hoje. Um LinkedHashMap preserva a ordem de inserção; um TreeMap visita as chaves em ordem classificada. Se duas pontuações empatarem, o laço anterior mantém a primeira visitada. Com um HashMap, qualquer um dos nomes empatados pode vencer. Adicione uma regra explícita de desempate quando o resultado precisar ser previsível.
Remova entradas pelo iterador
Chamar stock.remove(key) dentro de um laço for-each que percorre stock.keySet() altera as chaves usadas pelo laço. Isso pode causar uma ConcurrentModificationException. A detecção não é garantida; uma execução sem exceção não torna esse padrão válido.
Use o próprio método de remoção do iterador:
Iterator<Map.Entry<String, Integer>> it =
stock.entrySet().iterator();
while (it.hasNext()) {
if (it.next().getValue() == 0) {
it.remove();
}
}
Importe java.util.Iterator. Para maçã 15, pera 0, figo 0 e kiwi 4, isso remove pera e figo. Outra abordagem segura registra as chaves em uma lista, termina o laço e depois as remove.
Substituir um valor existente não adiciona nem remove uma chave. Durante um laço sobre entradas, entry.setValue(entry.getValue() * 2) pode dobrar as quantidades com segurança. Não adicione novas chaves por meio do mapa durante esse laço.
Distinga uma visão de uma cópia
stock.keySet().remove("apple") remove a entrada correspondente do mapa. Uma lista separada criada com new ArrayList<>(stock.keySet()) é uma cópia das chaves atuais. Ordenar essa lista não reordena o mapa, e remover um nome da lista não remove sua associação no mapa.
Principais conclusões
- Use
keySet,valuesouentrySetconforme as necessidades do laço. HashMapnão tem ordem de iteração garantida; resolva empates explicitamente.- Use o
removede um iterador para excluir durante o percurso. - Substituir um valor existente é permitido durante o percurso.
- As visões de um mapa estão vinculadas a ele; uma lista de chaves copiada é separada.
1.3 Use seus próprios objetos como chaves de mapas
Um ID de produto armazenado como String já tem regras de igualdade úteis. Uma chave criada a partir de sua própria classe exige uma decisão: dois objetos separados com os mesmos dados representam a mesma chave?
Códigos de dispersão limitam a busca; a igualdade a confirma
Um HashMap usa hashCode() para ajudar a localizar uma chave e equals() para verificar uma correspondência. Chaves iguais devem ter códigos de dispersão iguais. Chaves diferentes podem compartilhar um código de dispersão; a igualdade ainda as distingue. Classes padrão de valores, como String e Integer, já seguem esse contrato.
Sem sobrescritas, uma classe herda de Object a igualdade baseada em identidade. Dois pontos criados separadamente com coordenadas 2 e 3 são chaves diferentes, embora seus campos correspondam:
labels.put(new Point(2, 3), "door");
String label = labels.get(new Point(2, 3));
Com igualdade por identidade, label é null. A consulta criou um segundo objeto, diferente daquele usado na inserção.
Sobrescreva os dois métodos em conjunto
Aqui as coordenadas de um ponto definem seu conteúdo:
import java.util.Objects;
final class Point {
private final int x;
private final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Point)) {
return false;
}
Point point = (Point) other;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
A verificação de identidade trata rapidamente o caso do mesmo objeto. A verificação de tipo rejeita null e objetos de tipos não relacionados. A comparação final verifica as duas coordenadas. Objects.hash(x, y) constrói o código de dispersão a partir desses mesmos campos. Com essa classe, a consulta anterior retorna "door".
Sobrescrever apenas equals mantém o cálculo de hash herdado, que não garante códigos de dispersão iguais para objetos separados com campos iguais. Um mapa pode então deixar de encontrar uma chave igual. Um código de dispersão constante preservaria a correção, mas tornaria a busca lenta. Gerar as duas sobrescritas em um editor ajuda a evitar o uso de campos incompatíveis.
Use a assinatura exata do método
public boolean equals(Point other) faz uma sobrecarga do método; não substitui equals(Object). A consulta no mapa usa equals(Object), portanto a nova sobrecarga não fornece ao mapa igualdade por conteúdo. A anotação @Override faz uma assinatura errada gerar um erro de compilação em vez de um defeito oculto na consulta.
Mantenha estável a identidade da chave
Não altere campos que determinam a igualdade ou o código de dispersão de uma chave enquanto ela estiver armazenada. Se um ponto armazenado mudar de (2, 3) para (5, 3), o mapa pode deixar de encontrá-lo por qualquer um dos valores, embora size() permaneça igual. Remova-o antes de alterá-lo e depois insira-o novamente. Tornar os campos da chave final, como acima, evita esse erro.
Essas regras também determinam a pertinência em um HashSet. Um ArrayList usa equals para buscas por conteúdo, como contains; não precisa de códigos de dispersão para essa busca.
Principais conclusões
- Objetos iguais devem ter códigos de dispersão iguais; objetos diferentes podem compartilhar um código.
- Sobrescreva
equals(Object)ehashCode()com campos correspondentes. @Overridedetecta uma sobrecarga acidental deequals.- Mantenha inalterados os campos que definem a igualdade e o código de dispersão enquanto uma chave estiver armazenada.
2Conte, agrupe e indexe dados com mapas
Um mapa pode construir informações úteis enquanto um programa lê dados: uma contagem para cada palavra, uma lista para cada curso ou um objeto para cada ID. A escolha importante é o que cada valor representa. Um número acumula um resultado; uma lista ou um conjunto reúne um grupo; uma referência a objeto forma um índice. Acompanhe cada atualização a partir de um mapa vazio para que as primeiras ocorrências, as chaves repetidas e os objetos compartilhados tenham comportamentos claros.
2.1 Conte ocorrências e acumule totais por chave
Uma tabela de frequências tem uma chave para cada item distinto e um número que indica quantas vezes ele ocorre. A primeira ocorrência inicia uma contagem; cada ocorrência posterior atualiza essa mesma entrada.
Construa uma contagem, um item de cada vez
HashMap<String, Integer> counts = new HashMap<>();
for (String word : text.split(" ")) {
int oldCount = counts.getOrDefault(word, 0);
counts.put(word, oldCount + 1);
}
Para o texto “o gato viu o cão e o gato correu”, a primeira ocorrência de “o”, correspondente a "the" no texto original, ainda não está no mapa, portanto sua contagem anterior é 0 e a nova é 1. Suas duas ocorrências seguintes alteram essa entrada para 2 e depois para 3. A contagem de “gato”, correspondente a "cat", termina em 2; as contagens de “viu”, “cão”, “e” e “correu”, correspondentes a "saw", "dog", "and" e "ran", terminam em 1 cada.
Há 6 palavras distintas, portanto counts.size() é 6. A soma dos valores é 9, o número de ocorrências de palavras. Eles medem coisas diferentes: o tamanho do mapa não é o comprimento da sequência original.
A atualização pode ser escrita em uma linha:
counts.put(word, counts.getOrDefault(word, 0) + 1);
Uma forma equivalente mais longa verifica containsKey, incrementa uma contagem existente e armazena 1 para uma nova chave. Todas as contagens armazenadas nesse padrão são não nulas.
Preserve o resultado anterior
Chamar counts.put(word, 1) para cada palavra sobrescreve repetidamente cada contagem com 1. Isso registra que uma palavra existe, mas perde sua frequência. Chamar counts.get(word) + 1 sem tratar a primeira ocorrência tenta desempacotar null e falha. O valor padrão deve estar na etapa de leitura; a contagem aumentada deve então ser armazenada novamente.
Decida o que conta como o mesmo item
A igualdade de cadeias de caracteres é exata. "The" e "the" são chaves diferentes, assim como "cat" e "cat,". Se a tarefa as tratar como a mesma palavra, limpe cada unidade de entrada antes de contá-la. Converta o texto para minúsculas e remova a pontuação que o programa trata como separadores. Use uma regra consistente para que os resultados não dependam de qual grafia apareceu primeiro.
A chave também pode ser um caractere. Com HashMap<Character, Integer>, um laço sobre "banana".toCharArray() produz a=3, n=2 e b=1 usando o mesmo padrão de ler, aumentar e armazenar.
Acumule quantias em vez de ocorrências
Para totais por categoria, adicione a quantia atual em vez de 1:
HashMap<String, Double> totals = new HashMap<>();
double oldTotal = totals.getOrDefault(category, 0.0);
totals.put(category, oldTotal + amount);
Alimentação 12,50, transporte 3,20 e alimentação 7,25 resultam em alimentação 19,75 e transporte 3,20. O valor padrão é 0.0, correspondente ao tipo de valor Double. O mapa continua tendo uma entrada por categoria, independentemente de quantas quantias contribuíram para ela.
Interprete a tabela concluída
Percorra as entradas para encontrar a maior contagem ou o maior total, guardando a melhor chave e seu valor. Especifique uma regra de desempate, se necessário. Para um relatório em ordem alfabética, new TreeMap<>(counts) copia as associações em ordem classificada de chaves. Os valores das contagens permanecem inalterados; ordenar as chaves não ordena as categorias por seus totais.
Principais conclusões
- Um mapa de frequências armazena uma contagem por chave distinta.
- Leia a contagem anterior com zero como valor padrão, adicione um e armazene o resultado.
- O tamanho do mapa conta itens distintos; a soma das contagens mede as ocorrências.
- Normalize o texto de forma consistente antes de contar.
- Use o mesmo padrão de atualização para somar quantias por chave.
- Escolha a ordem do relatório separadamente dos valores acumulados.
2.2 Agrupe valores sob uma mesma chave usando listas e conjuntos como valores
Um valor de mapa pode ser uma coleção. Quando vários alunos pertencem a um curso, o curso é uma chave e a lista associada contém todos os seus alunos. A regra de chave única do mapa continua válida: a lista é o único valor daquele curso.
Crie um grupo antes de adicionar itens a ele
HashMap<Character, ArrayList<String>> groups = new HashMap<>();
for (String fruit : fruits) {
char letter = fruit.charAt(0);
if (!groups.containsKey(letter)) {
groups.put(letter, new ArrayList<>());
}
groups.get(letter).add(fruit);
}
Para “apple”, “banana”, “avocado”, “cherry” e “blueberry”, a primeira fruta cria a lista de a e adiciona “apple”. “Banana” cria a lista de b. “Avocado” encontra a lista existente de a e é adicionado a ela. O resultado é a → [apple, avocado], b → [banana, blueberry] e c → [cherry]. Cada lista mantém sua própria ordem de inserção, embora o HashMap não ordene suas chaves.
A verificação pode ser abreviada:
groups.putIfAbsent(letter, new ArrayList<>());
groups.get(letter).add(fruit);
putIfAbsent mantém uma lista existente não nula. O get seguinte retorna essa lista, pronta para receber o item.
Mantenha a lista que você já construiu
Um groups.put(letter, new ArrayList<>()) incondicional dentro do laço substitui a lista anterior a cada ocorrência. Apenas a última fruta de cada letra permanece depois do add seguinte. O erro oposto é deixar de criar a lista: groups.get(letter).add(fruit) lança uma NullPointerException para uma nova chave porque ainda não existe uma lista.
Entenda a referência
get retorna a referência à lista armazenada. Adicionar um item a ela altera essa mesma lista, portanto não é necessário inseri-la novamente. Isso também explica um erro de compartilhamento:
ArrayList<String> shared = new ArrayList<>();
courses.put("Art", shared);
courses.put("Music", shared);
courses.get("Art").add("Jin");
Agora ambas as chaves levam a [Jin]. Duas chaves não criaram duas listas. Crie uma nova lista para cada novo grupo quando os grupos precisarem ser independentes.
Escolha listas ou conjuntos dentro dos grupos
Uma lista preserva adições repetidas. Um conjunto impede duplicatas dentro do grupo. Um HashMap<String, HashSet<String>> pode, portanto, reunir as matrículas distintas dos alunos sem contar o mesmo aluno duas vezes em um curso. A regra do conjunto se aplica dentro de cada valor; o mapa externo continua tendo uma entrada por curso.
Para ler um grupo que pode estar ausente, verifique containsKey ou use groups.getOrDefault(letter, new ArrayList<>()). Uma chave ausente então produz uma lista vazia para essa chamada. A lista padrão não é inserida automaticamente; adicionar um item a ela não cria um grupo armazenado.
Remover o último item de um grupo deixa a chave associada a uma coleção vazia. Se o programa não deve mais listar grupos vazios, verifique isEmpty() e remova também essa chave. Conte os grupos pelo tamanho do mapa externo e os itens pelos tamanhos das coleções internas.
Principais conclusões
- Garanta que um grupo exista e depois adicione itens à sua lista ou ao seu conjunto armazenado.
- Crie uma nova coleção para cada grupo independente.
getretorna a referência armazenada, portanto alterações internas não precisam de outroput.- Valores do tipo lista mantêm repetições; valores do tipo conjunto mantêm membros distintos em cada grupo.
- Um grupo vazio armazenado ainda tem uma entrada no mapa.
2.3 Consulte objetos e preços rapidamente com um índice baseado em mapa
Um índice associa uma chave de identificação a um objeto. Uma biblioteca pode encontrar um livro pelo ISBN sem percorrer todos os livros de uma lista. Uma tabela de consulta usa a mesma estrutura para associar um código a um valor simples, como o preço de um produto.
Escolha uma chave de identificação
Um HashMap<String, Book> pode associar um ISBN ao seu livro. Cada consulta precisa apenas da chave. O nome de uma pessoa muitas vezes é uma chave única inadequada: armazenar outra pessoa chamada “Sam Lee” sob essa mesma cadeia de caracteres substitui a pessoa anterior. Use um ID único ou um mapa de agrupamento se um nome deve levar a várias pessoas.
Mantenha um índice dentro da classe responsável pelos dados:
class Library {
private HashMap<String, Book> byIsbn;
Library() {
byIsbn = new HashMap<>();
}
void addBook(Book book) {
byIsbn.put(book.getIsbn(), book);
}
Book findByIsbn(String isbn) {
return byIsbn.get(isbn);
}
}
Aqui Book fornece um método getIsbn(). Quem chama a classe usa addBook e findByIsbn; não precisa saber qual implementação de mapa está armazenada. O campo privado também dá à classe um único lugar para manter suas regras de adição e substituição de livros.
Verifique um resultado ausente
Se findByIsbn retornar null, nenhum livro foi encontrado. Teste o resultado antes de chamar um método nele:
Book found = library.findByIsbn("978-0-00-000000-2");
if (found != null) {
found.setOnLoan(true);
}
Chamar setOnLoan diretamente em um resultado ausente lançaria uma NullPointerException. Um método como hasBook(isbn) é outra forma de permitir que quem chama o método verifique a existência de uma chave.
Acompanhe objetos compartilhados entre índices
Um mapa armazena uma referência a um objeto, não uma nova cópia desse objeto. Se o mesmo livro estiver em uma lista de todos os livros, em um mapa por ISBN e em um agrupamento por autor, setOnLoan(true) alterará o único livro ao qual os três se referem. Isso evita que três objetos de livro separados se tornem inconsistentes.
As próprias estruturas de coleção ainda precisam ser mantidas. Remover um livro do mapa por ISBN não remove sua referência da lista de um autor. Se uma biblioteca mantiver os dois índices, seus métodos de adição e remoção deverão atualizar ambos. Centralizar essas alterações em métodos como addBook e removeBook ajuda a manter as buscas consistentes.
Use uma tabela em um cálculo
Suponha que uma tabela de preços tenha café 2,50, chá 2,00 e muffin 3,25. Para dois cafés e um muffin:
double cost = 2 * prices.get("coffee") + prices.get("muffin");
O subtotal dos cafés é 5,00; somar 3,25 resulta em 8,25. As chaves identificam produtos, e os valores fornecem as quantias. Um produto ausente exige uma decisão explícita antes do cálculo: um valor padrão zero o trataria como gratuito sem aviso. A mesma técnica de consulta pode, portanto, precisar de uma regra para chaves ausentes diferente daquela de uma tabela de frequências.
Principais conclusões
- Um índice encontra objetos por uma chave de identificação.
- Use uma chave única ou agrupe explicitamente vários objetos correspondentes.
- Índices compartilham referências a objetos, mas adições e remoções devem atualizar cada índice.
- Mantenha mapas de dados privados e disponibilize métodos que mantenham suas regras.
3Mantenha valores únicos com conjuntos
Às vezes a pergunta é simplesmente se um valor já apareceu antes. Conjuntos atendem diretamente a essa necessidade e também podem comparar grupos de valores, como pessoas que participam de dois eventos. A ausência de elementos duplicados muda tanto o código que você escreve quanto o significado do tamanho final. Trabalhe primeiro com pertinência, depois combine conjuntos e escolha se seus valores devem aparecer em ordem de inserção ou em ordem classificada.
3.1 Armazene valores únicos e teste a pertinência com HashSet
Um conjunto contém cada valor no máximo uma vez. Ele é adequado para perguntas como “Esse valor já apareceu antes?” ou “Quantos valores diferentes aparecem?”. Um HashSet oferece verificações de pertinência rápidas em média, sem garantir uma ordem de exibição.
Adicione e verifique valores
import java.util.HashSet;
HashSet<String> visited = new HashSet<>();
boolean first = visited.add("Oslo");
boolean second = visited.add("Lima");
boolean third = visited.add("Oslo");
visited.add("Pune");
Os três valores booleanos armazenados são true, true e false. O segundo “Oslo” corresponde a um elemento existente, portanto não é adicionado. O tamanho do conjunto é 3. Uma adição duplicada não substitui uma posição numerada, pois um conjunto não tem índice.
visited.contains("Lima") retorna true. visited.remove("Lima") remove o valor e retorna true; repetir essa remoção retorna false. Use um laço for-each para visitar os valores. Não existe get(0) para o primeiro valor de um HashSet.
Remova duplicatas de uma lista
ArrayList<Integer> values = new ArrayList<>();
values.add(3);
values.add(1);
values.add(3);
values.add(2);
values.add(1);
HashSet<Integer> distinct = new HashSet<>(values);
O conjunto tem três valores: {1, 2, 3}. Sua ordem real de iteração não é especificada. A lista original ainda tem cinco elementos porque o construtor cria uma coleção separada.
Use new LinkedHashSet<>(values) para manter a ordem das primeiras ocorrências, obtendo 3, 1, 2. Use new TreeSet<>(values) para obter valores ordenados, 1, 2, 3. Os conjuntos são escritos entre chaves aqui para destacar a pertinência; o toString() padrão de conjuntos em Java usa colchetes.
Detecte a primeira repetição
O resultado de add pode realizar o teste de pertinência e a inserção juntos:
HashSet<Integer> seen = new HashSet<>();
for (int number : numbers) {
if (!seen.add(number)) {
System.out.println(number);
break;
}
}
Para [4, 7, 2, 7, 4], o laço exibe 7. Esse é o primeiro valor encontrado uma segunda vez, embora 4 tenha aparecido antes na sequência. Antes de 7 se repetir, o conjunto contém 4, 7 e 2. A inserção que falha provoca a interrupção.
Saiba o que um conjunto não pode informar
Verificar contains antes de cada add é desnecessário porque add já trata duplicatas. Uma lista com uma verificação contains também pode manter valores únicos, mas cada busca na lista pode percorrer todos os elementos armazenados. Um HashSet expressa a regra diretamente.
A igualdade importa para seus próprios objetos. Um HashSet<Point> precisa de equals baseado no conteúdo e de um hashCode compatível para reunir pontos criados separadamente com coordenadas iguais. Sem essas sobrescritas, instâncias separadas permanecem como elementos separados.
Por fim, size() mede valores distintos, não ocorrências. As nove palavras de “o gato viu o cão e o gato correu” produzem seis palavras distintas. Um conjunto não informa mais que “o” ocorreu três vezes; use um mapa de frequências quando essas contagens importarem.
Principais conclusões
HashSetarmazena valores únicos sem índice nem ordem garantida.addretorna falso quando um valor igual já está presente.- Um conjunto criado por cópia remove duplicatas sem alterar a lista original.
- Use o resultado de
addpara detectar um valor repetido. - O tamanho de um conjunto conta valores distintos; frequências exigem um mapa.
3.2 Combine conjuntos e mantenha sua ordem
Conjuntos podem descrever grupos e comparar seus membros. Se duas listas de eventos contiverem a mesma pessoa várias vezes, um conjunto primeiro reduz cada lista às pessoas que participaram. As operações de conjuntos então respondem a perguntas sobre qualquer um dos eventos, ambos ou apenas um deles.
Combine dois grupos
Considere que segunda-feira seja {Ana, Ben, Cai, Dee} e terça-feira seja {Ben, Dee, Eva}.
| Pergunta | Método em uma cópia de segunda-feira | Resultado |
|---|---|---|
| Quem participou em qualquer um dos dias? | addAll(tuesday) | {Ana, Ben, Cai, Dee, Eva} |
| Quem participou nos dois dias? | retainAll(tuesday) | {Ben, Dee} |
| Quem participou somente na segunda-feira? | removeAll(tuesday) | {Ana, Cai} |
Essas operações são união, interseção e diferença. Elas alteram o conjunto receptor e retornam um valor booleano que indica se ele foi alterado. Elas não retornam um novo conjunto como resultado.
Preserve o original
Faça uma cópia antes de alterar os membros se segunda-feira ainda for necessária:
HashSet<String> both = new HashSet<>(monday);
both.retainAll(tuesday);
both começa com os quatro nomes de segunda-feira. retainAll remove Ana e Cai porque eles não estão em terça-feira. O próprio conjunto de segunda-feira permanece inalterado. Para encontrar quem participou somente na terça-feira, comece com uma cópia de terça-feira e remova os nomes de segunda-feira, obtendo {Eva}. A diferença tem uma direção; invertê-la muda a pergunta.
Verifique subconjuntos e igualdade
monday.containsAll(group) verifica se todos os valores de group estão presentes em segunda-feira. Para {Ben, Dee}, retorna true: esse grupo é um subconjunto de segunda-feira. Isso não exige que segunda-feira contenha apenas essas duas pessoas.
Dois conjuntos são iguais quando seus elementos correspondem, independentemente da ordem de inserção ou da implementação. Um HashSet que contém “x” e “y” é igual a um TreeSet que contém “y” e “x”. A pertinência determina a igualdade de conjuntos, portanto a ordem por si só não pode torná-los diferentes.
Escolha uma ordem para o percurso
| Implementação | Ordem ao visitar os elementos |
|---|---|
HashSet | Sem garantia |
LinkedHashSet | Ordem de inserção |
TreeSet | Ordem classificada |
Os três evitam duplicatas. Use LinkedHashSet quando a primeira ocorrência de cada nome for importante. Use TreeSet quando cada percurso já precisar estar ordenado. Para cadeias de caracteres, a ordenação natural segue os códigos dos caracteres: formas minúsculas e maiúsculas não se comportam como um único alfabeto sem distinção entre elas.
Um TreeSet com seu construtor padrão precisa de elementos que tenham uma comparação natural, como cadeias de caracteres, números ou objetos que implementem Comparable. Nesse conjunto, um resultado de comparação igual a zero indica uma duplicata. Uma classe que não fornece comparação natural causa uma ClassCastException quando um de seus objetos é inserido. Fornecer um comparador explícito é outra forma de definir a ordem de uma coleção em árvore; os exemplos com construtor padrão usam a ordem natural.
Principais conclusões
addAll,retainAlleremoveAllalteram o conjunto receptor.- Copie primeiro um conjunto quando seus membros originais ainda forem necessários.
containsAllverifica um subconjunto; a igualdade de conjuntos ignora a ordem.- Escolha implementações baseadas em hash, vinculadas ou em árvore para obter, respectivamente, ordem não especificada, de inserção ou classificada.
4Programe com as interfaces List, Set e Map
O tipo à esquerda de uma declaração de coleção informa ao restante do programa quais operações ele pode usar. A classe à direita fornece essas operações e pode garantir uma ordem específica. Aprender a interpretar os dois lados torna o código com coleções mais fácil de alterar e os métodos mais fáceis de reutilizar. Isso também ajuda a explicar por que uma lista, um conjunto e um mapa se comportam de maneira diferente mesmo quando contêm dados de aparência semelhante.
4.1 Declare variáveis e parâmetros com tipos de interface
Uma interface descreve operações fornecidas por uma classe que a implementa. Ela permite que uma variável descreva o que o código precisa, deixando a escolha do armazenamento para uma classe concreta. List, Set e Map são interfaces relacionadas a coleções em java.util.
Interprete os dois lados de uma declaração
List<String> names = new ArrayList<>();
Set<String> tags = new HashSet<>();
Map<String, Integer> counts = new HashMap<>();
O lado esquerdo declara o tipo da variável. O lado direito cria um objeto de uma classe que implementa esse tipo. Importe ambos os tipos, como java.util.List e java.util.ArrayList. Você não pode escrever new List<>() ou new Map<>(): uma interface não é um objeto concreto que possa ser construído.
O código que usa counts pode chamar put, get e entrySet porque Map os declara. Se chaves em ordem alfabética se tornarem úteis, altere a construção para new TreeMap<>(). As chamadas existentes continuam compilando. Sua ordem pode mudar porque as implementações podem oferecer garantias diferentes de ordem; a interface não as torna idênticas em todos os comportamentos.
Aceite a capacidade de que um método precisa
Um método que apenas conta palavras longas pode receber uma Collection:
static int countLong(Collection<String> words, int min) {
int count = 0;
for (String word : words) {
if (word.length() >= min) {
count++;
}
}
return count;
}
Para [“a”, “tree”, “house”] e um mínimo de 4, ele retorna 2. O mesmo método pode receber um ArrayList, um LinkedList, um HashSet ou List.of(...) porque apenas lê os elementos. Um conjunto pode já ter removido duplicatas, portanto pode fornecer dados de entrada diferentes dos de uma lista.
Usar um parâmetro de tipo de interface evita exigir uma classe específica de armazenamento quando o método não precisa dela. Se posições forem necessárias, aceite List. Se consultas por chave forem necessárias, aceite Map.
Conheça os limites do tipo declarado
List<String> names = new ArrayList<>();
names.ensureCapacity(100); // does not compile
O objeto é um ArrayList, mas List não declara ensureCapacity. O compilador verifica o tipo declarado da variável. Use um tipo de classe concreta quando sua operação especial for realmente necessária; não altere parâmetros de listas comuns apenas para corresponder à classe usada por quem chama o método.
Posicione Map ao lado de Collection
List e Set estendem Collection, que descreve um grupo de elementos. Ela declara métodos como add, remove, contains, size, isEmpty, addAll e clear. A possibilidade de fazer uma alteração depende da coleção concreta.
Map não estende Collection. Ele armazena associações e fornece visões que são coleções: keySet() é um Set, values() é uma Collection e entrySet() é um Set de entradas. Passe counts.values() a um método que precise de uma coleção de valores, não o próprio counts.
Uma classe pode implementar várias interfaces. LinkedList implementa tanto List quanto Deque, uma interface de fila de duas extremidades. Sua própria classe indica as interfaces que se compromete a implementar depois de implements, como em class Member implements Comparable<Member>.
Principais conclusões
- Declare a interface necessária à esquerda e construa uma classe que a implemente à direita.
- Parâmetros de tipo de interface aceitam diferentes implementações com as operações necessárias.
- Uma variável disponibiliza apenas os métodos declarados por seu tipo.
ListeSetestendemCollection;Mapfornece visões de coleção.
4.2 Conheça as garantias de List, Set e Map
Escolha uma interface pelas regras de que seus dados precisam. Conteúdos de aparência semelhante não tornam uma lista, um conjunto e um mapa intercambiáveis: cada um atribui um significado diferente a posições, repetições e igualdade.
Compare as garantias
| Interface | O que armazena | Regra importante |
|---|---|---|
List | Elementos em posições a partir de 0 | Elementos repetidos são permitidos |
Set | Elementos distintos | Não tem operação get por índice |
Map | Pares chave–valor | Chaves são únicas; valores podem se repetir |
ArrayList e LinkedList implementam List. HashSet, LinkedHashSet e TreeSet implementam Set. HashMap, LinkedHashMap e TreeMap implementam Map. As versões baseadas em hash não garantem ordem de percurso; as versões vinculadas preservam a ordem de inserção; as versões em árvore mantêm elementos ou chaves ordenados. Inserir novamente uma chave existente em um LinkedHashMap comum, ordenado por inserção, mantém a posição dessa chave.
Examine com cuidado a remoção em listas de inteiros
Uma List<Integer> tem duas sobrecargas relevantes:
List<Integer> numbers = new ArrayList<>(List.of(1, 5, 7));
numbers.remove(1);
O argumento 1 é um int, portanto Java remove o índice 1: o valor 5. O resultado é [1, 7]. Começando novamente com [1, 5, 7], numbers.remove(Integer.valueOf(1)) seleciona a remoção por valor e deixa [5, 7]. O objeto empacotador deixa clara a sobrecarga pretendida.
Compare conteúdos com a regra correta
Duas listas são iguais quando os mesmos elementos aparecem na mesma ordem. Um ArrayList [1, 2] é igual a um LinkedList [1, 2], mas não a uma lista [2, 1]. Dois conjuntos comparam a pertinência, ignorando a ordem. Dois mapas comparam suas associações, portanto a ordem de inserção não afeta a igualdade dos mapas. Suas classes concretas podem ser diferentes enquanto seus conteúdos são iguais segundo a regra da interface.
Reconheça coleções não modificáveis
List<String> labels = List.of("a", "b");
Set<Integer> levels = Set.of(1, 2, 3);
Map<String, Double> prices = Map.of("tea", 2.0, "coffee", 2.5);
Essas fábricas retornam coleções não modificáveis. Tentativas de adicionar, remover, substituir ou ordenar seu conteúdo lançam UnsupportedOperationException. Map.of aceita até dez pares chave–valor.
As três rejeitam elementos, chaves ou valores null com NullPointerException. Set.of rejeita elementos duplicados e Map.of rejeita chaves duplicadas com IllegalArgumentException. List.of permite duplicatas porque uma lista pode repetir um elemento. Os conjuntos e mapas produzidos pelas fábricas têm ordem de iteração não especificada.
Copie quando alterações forem necessárias
new ArrayList<>(labels) cria uma lista modificável com os mesmos elementos. new HashSet<>(someList) e new HashMap<>(someMap) também criam estruturas de coleção separadas.
Essas cópias são superficiais: elas contêm as mesmas referências aos elementos. Remover um elemento de uma cópia deixa a estrutura original intacta, mas alterar um objeto mutável por meio de qualquer uma das coleções altera o objeto compartilhado. Uma coleção não modificável impede alterações em sua estrutura; ela não congela todos os objetos armazenados nela.
Principais conclusões
- Listas têm posições e duplicatas; conjuntos têm elementos distintos; mapas têm chaves únicas.
remove(1)em uma lista de inteiros remove por índice;remove(Integer.valueOf(1))remove por valor.- A igualdade de listas verifica a ordem; a igualdade de conjuntos e mapas verifica o conteúdo sem considerar a ordem de inserção.
- As fábricas
ofproduzem coleções não modificáveis e rejeitam valores nulos. Set.ofrejeita elementos duplicados;Map.ofrejeita chaves duplicadas.- Uma cópia modificável tem uma estrutura de coleção separada, mas compartilha as referências aos elementos.
5Ordene coleções com Comparable
A ordenação coloca valores em uma ordem que outras partes do código podem usar. Números e cadeias de caracteres já têm sua ordem natural; objetos de suas próprias classes precisam de uma regra explícita. Acompanhe uma lista durante uma ordenação e depois escreva uma comparação que trate números, texto e empates com segurança. A regra importa além das listas: um conjunto ou mapa ordenado também a usa para decidir quando dois elementos ou chaves ocupam a mesma posição.
5.1 Ordene listas de números e cadeias de caracteres
Uma lista mantém uma ordem, mas essa ordem pode apenas refletir como os valores chegaram. A ordenação reorganiza a lista usando uma regra de comparação. Java já fornece uma ordem natural para números e cadeias de caracteres.
Ordene uma lista modificável na própria lista
List<Double> values = new ArrayList<>(List.of(3.5, -1.0, 2.25));
Collections.sort(values);
Importe java.util.Collections. A mesma lista agora contém [-1,0; 2,25; 3,5]. A ordenação retorna void, portanto values = Collections.sort(values) não compila. values.sort(null) também ordena em ordem natural. Para um vetor, use Arrays.sort(array); um vetor contendo 5, 2 e 8 passa a conter 2, 5, 8.
Preveja a ordem de cadeias caractere por caractere
A comparação de cadeias examina o primeiro caractere diferente. Se uma cadeia for prefixo de outra, a mais curta vem primeiro. Assim, “apple” vem antes de “apples”.
A lista [“pear”, “Banana”, “apple”, “10”, “9”] é ordenada como [“10”, “9”, “Banana”, “apple”, “pear”]. Para esses caracteres, algarismos precedem letras maiúsculas, e maiúsculas precedem minúsculas. “10” vem antes de “9” porque “1” vem antes de “9”; a ordem de cadeias não interpreta cadeias de algarismos como números inteiros. Armazene dados numéricos como números quando a ordem numérica for necessária.
Use ordens alternativas prontas
names.sort(String.CASE_INSENSITIVE_ORDER);
values.sort(Collections.reverseOrder());
A primeira chamada ordena [“pear”, “Banana”, “apple”] como [“apple”, “Banana”, “pear”] sem alterar as letras maiúsculas e minúsculas armazenadas. A segunda usa a ordem natural decrescente. Os números 4, 9 e 1 tornam-se 9, 4 e 1. Esses argumentos são comparadores, objetos que fornecem uma ordem alternativa.
Collections.reverse(list) apenas inverte a sequência atual. Ele produz ordem decrescente se essa sequência já estava ordenada de forma crescente; sozinho, não ordena uma lista arbitrária.
Mantenha os empates estáveis
A ordenação de listas é estável: elementos considerados iguais na comparação mantêm sua ordem relativa anterior. Se uma comparação apenas por pontuação empatar duas pessoas, a ordem anterior delas na lista permanece. A estabilidade preserva essa ordem de entrada; ela não cria um critério de desempate alfabético.
Reconheça falhas e atalhos
Uma lista criada com List.of(...) não pode ser ordenada na própria lista. Primeiro copie-a para um ArrayList. Para uma classe sem Comparable, Collections.sort(list) falha na verificação de tipos durante a compilação. Chamar list.sort(null) em objetos desse tipo falha em tempo de execução com ClassCastException quando a comparação é necessária.
Collections.max(collection) e Collections.min(collection) encontram o maior e o menor elemento em ordem natural sem reorganizar a coleção. Eles lançam NoSuchElementException para uma coleção vazia.
Para obter chaves de mapa ordenadas, copie map.keySet() para um ArrayList e ordene a cópia, ou use um TreeMap. Ordenar uma lista copiada de chaves deixa inalterada a ordem de iteração do próprio mapa.
Principais conclusões
Collections.sortaltera uma lista modificável na própria lista e retornavoid.- A ordem natural de cadeias compara caracteres, não os valores numéricos no texto.
- Use comparadores prontos para ordem inversa ou sem distinção entre maiúsculas e minúsculas.
- A ordenação estável preserva a ordem relativa anterior dos elementos empatados.
- Copie uma lista não modificável antes de ordená-la.
minemaxencontram valores extremos sem ordenar.
5.2 Implemente Comparable em sua própria classe
Java não consegue adivinhar se um membro deve vir primeiro pelo nome, pela altura ou por outro campo. Implemente Comparable para dar à classe uma ordem natural. O código de ordenação pode então pedir que cada objeto se compare a outro objeto dessa classe.
Escreva o método de comparação
class Member implements Comparable<Member> {
private String name;
private int height;
Member(String name, int height) {
this.name = name;
this.height = height;
}
@Override
public int compareTo(Member other) {
return Integer.compare(this.height, other.height);
}
}
A altura é medida em centímetros. Comparable<Member> especifica que o outro objeto é um Member; nenhuma conversão explícita é necessária. public int compareTo(Member other) é o método exigido. A interface padrão Comparable está em java.lang, portanto não precisa ser importada.
Para a.compareTo(b), um resultado negativo coloca a antes de b, zero os coloca na mesma posição de comparação e um resultado positivo coloca a depois de b. Apenas o sinal importa: -35 é um resultado negativo tão válido quanto -1.
Acompanhe a ordem
Com a comparação por altura, Ana 172, Ben 165 e Cai 180 são ordenados como Ben 165, Ana 172 e Cai 180. Para colocar os membros mais altos primeiro, inverta os argumentos:
return Integer.compare(other.height, this.height);
Altere a regra de forma deliberada. Inverter os argumentos inverte o sentido desse campo; isso não muda o significado da altura nem altera os dados de qualquer membro.
Compare valores numéricos inteiros com segurança
A subtração parece conveniente, mas pode retornar o sinal errado quando ocorre estouro de um int. Para -2.000.000.000 e 2.000.000.000, subtrair o segundo do primeiro produz, por estouro, 294.967.296, um resultado positivo. Integer.compare retorna corretamente um resultado negativo.
Para campos decimais, use Double.compare(this.price, other.price). Converter explicitamente uma diferença para int perde informação: (int) (1.8 - 1.5) é 0, portanto preços diferentes tornam-se um empate na comparação. Um método auxiliar de comparação preserva a ordem sem truncar a diferença.
Compare texto e reutilize a regra
Para ordenar por nome, retorne this.name.compareTo(other.name). Ele segue a ordem dos caracteres da cadeia. compareToIgnoreCase fornece comparação de texto sem distinção entre maiúsculas e minúsculas quando essa é a regra pretendida para o campo.
Depois que uma classe define uma ordem natural, operações como Collections.sort, Collections.max e as comparações padrão de TreeSet ou TreeMap podem usá-la. Uma classe também pode implementar outras interfaces, separadas por vírgulas depois de implements.
Há uma ordem natural para a classe, não um compareTo diferente selecionado para cada lista. Use objetos comparadores separados quando um contexto precisar de ordem por nome e outro de ordem por altura. Uma comparação apenas por altura também empata todas as alturas iguais; decidir se esse empate é aceitável torna-se especialmente importante em conjuntos ordenados.
Principais conclusões
- Implemente
Comparable<YourClass>com um método públicocompareTo. - Resultados negativo, zero e positivo significam, respectivamente, antes, empate e depois.
- Use
Integer.compareeDouble.comparepara uma ordenação numérica segura. - Inverta os argumentos da comparação para inverter o sentido de um campo.
- Uma classe tem uma ordem natural; comparadores fornecem outras ordens.
5.3 Resolva empates e use conjuntos e mapas ordenados
Uma comparação principal muitas vezes deixa empates. Dois filmes podem ter o mesmo ano ou dois jogadores podem ter a mesma pontuação. Um critério de desempate dá vez ao campo seguinte somente quando os campos anteriores são considerados iguais na comparação.
Compare os campos em ordem de prioridade
@Override
public int compareTo(Film other) {
int byYear = Integer.compare(this.year, other.year);
if (byYear != 0) {
return byYear;
}
return this.title.compareTo(other.title);
}
O ano é a regra principal. O título só importa quando os anos empatam. Up (2009), Avatar (2009) e Alien (1979) são ordenados como Alien (1979), Avatar (2009), Up (2009). Comparar os títulos primeiro daria a eles prioridade sobre o ano e atenderia a uma tarefa de ordenação diferente.
Os sentidos podem ser diferentes para cada campo. Para colocar as maiores pontuações primeiro e os nomes de A a Z, comece com Integer.compare(other.points, this.points). Se o resultado for zero, retorne this.name.compareTo(other.name). Inverter toda a lista final também inverteria os nomes dentro das pontuações empatadas.
Entenda a regra de duplicatas de um conjunto ordenado
Um TreeSet<Member> padrão usa a comparação natural tanto para ordenar elementos quanto para decidir quando um elemento já está presente. Se Member.compareTo usar apenas a altura, Ana 172 e Dee 172 terão comparação igual a zero. Adicionar Ana retorna true; adicionar Dee retorna false. Ana permanece como elemento armazenado mesmo que equals considere as duas integrantes diferentes.
Uma lista pode manter os dois objetos empatados; um conjunto em árvore dá a eles uma única posição de comparação. Adicione o critério de desempate necessário se eles precisarem ser distintos no conjunto.
Alinhe a comparação à igualdade
Uma ordem é consistente com equals quando a comparação retorna zero se, e somente se, equals retorna verdadeiro. Para uma classe cuja igualdade usa altura e nome, comparar primeiro a altura e depois o nome pode atender a essa regra. Se a igualdade usar outra identidade, como um ID de membro, adicionar apenas o nome como critério de desempate não estabelece a consistência.
A comparação também deve se comportar como uma ordem válida. Se a vem antes de b, a comparação inversa deve colocar b depois de a. Se a está antes de b e b antes de c, a deve estar antes de c. Usar métodos auxiliares de comparação de campos completos em uma ordem fixa de prioridade ajuda a cumprir essas regras. Um método inconsistente pode ordenar resultados incorretamente ou fazer uma ordenação lançar IllegalArgumentException.
Mantenha as chaves do mapa ordenadas também
Um TreeMap ordena chaves, não valores. Para as contagens de palavras de “o gato viu o cão e o gato correu”, a primeira chave é “cão” e a última é “viu”. firstKey() e lastKey() fornecem esses extremos. Declare um TreeMap ou uma interface apropriada de mapa ordenado ao chamar métodos que o Map comum não declara.
A comparação de chaves também define quais chaves correspondem. Uma segunda chave cuja comparação resulta em zero atualiza a associação existente, mesmo quando equals distingue os objetos. Coleções em árvore com comportamento padrão exigem elementos ou chaves comparáveis naturalmente; inserir um objeto sem comparação adequada lança ClassCastException. Um comparador fornecido explicitamente pode definir outra ordem.
Principais conclusões
- Compare primeiro o campo principal e consulte os campos seguintes apenas em caso de empate.
- Inverta apenas os campos que precisam de ordem decrescente.
- Coleções em árvore tratam uma comparação igual a zero como o mesmo elemento ou a mesma chave.
- A consistência com
equalsexige que a comparação seja zero exatamente quando a igualdade for verdadeira. TreeMapordena chaves; seus métodos de extremidade retornam as chaves extremas.- Uma comparação deve inverter os sinais de forma consistente e preservar a ordem entre três elementos.
6Escolha a coleção adequada para uma tarefa
A escolha de uma coleção começa pelas perguntas que o programa deve responder: por posição, por pertinência ou por uma chave separada. Ordem e duplicatas restringem ainda mais a escolha. Depois que os dados se ajustarem à tarefa, compare como as operações frequentes crescem à medida que chegam mais valores. Uma pequena alteração, como criar um conjunto antes de um laço, pode eliminar buscas repetidas sem tornar o programa mais difícil de ler.
6.1 Compare o custo de operações comuns em coleções
O custo de uma operação descreve como seu trabalho cresce com o número de elementos armazenados. Ele ajuda a identificar código que é rápido para um exemplo pequeno, mas lento quando a coleção se torna grande.
Compare o crescimento, não os segundos
O tempo constante, O(1), permanece aproximadamente independente do tamanho da coleção. O tempo linear, O(n), pode crescer em proporção ao número de elementos. O tempo logarítmico, O(log n), cresce lentamente à medida que o tamanho aumenta. Essas designações descrevem o crescimento, não tempos exatos de execução em um computador específico.
| Coleção | Operação | Custo |
|---|---|---|
ArrayList | get(i), set(i, x) | Constante |
ArrayList | Adicionar ao final | Constante em média |
ArrayList | contains, indexOf, remover por valor | Linear |
ArrayList | Inserir ou remover perto do início | Linear |
HashMap / HashSet | Consulta básica por chave ou pertinência, inserção, remoção | Constante em média com hashes bem distribuídos |
TreeMap / TreeSet | Consulta básica, inserção, remoção | Logarítmico |
LinkedList | Adicionar ou remover em qualquer extremidade | Constante |
LinkedList | get(i) em geral | Linear |
Uma busca em ArrayList pode verificar todos os elementos; alterações no início deslocam os elementos seguintes. Um LinkedList precisa percorrer a lista até uma posição, portanto o acesso repetido por índice pode ser custoso. ArrayList é uma escolha padrão útil para o trabalho comum com listas.
Identifique o percurso repetido
Suponha que um programa verifique 10.000 nomes em uma lista que contém 100.000 nomes. Chamar list.contains(name) para cada nome pode exigir até 1.000.000.000 de verificações de igualdade. Uma chamada de método que parece rápida ainda é uma busca completa quando usada dessa forma.
Construa um conjunto para verificar a pertinência uma única vez:
Set<String> allowed = new HashSet<>(allowedNames);
int matches = 0;
for (String name : incomingNames) {
if (allowed.contains(name)) {
matches++;
}
}
Há trabalho para construir o conjunto de 100.000 elementos, seguido de 10.000 verificações de pertinência em tempo constante em média. Contando as duas etapas, o total cresce aproximadamente com a soma dos tamanhos das duas entradas, em vez de seu produto. Reconstruir o conjunto dentro do laço repetiria o trabalho de preparação e eliminaria esse benefício.
Interprete corretamente as garantias médias
Operações baseadas em hash dependem de chaves cujos códigos de dispersão distribuam bem os valores. Retornar um código de dispersão constante para todos os objetos ainda pode satisfazer as regras de igualdade, mas torna a consulta lenta. Isso não é uma maneira sem custo de evitar escrever um método de hash útil.
Coleções em árvore mantêm a ordem classificada com operações básicas logarítmicas. Dobrar o número de elementos acrescenta apenas uma pequena quantidade de trabalho à busca. Para 100.000 elementos, um logaritmo de base dois é aproximadamente 16,6; isso indica a escala da busca, não uma garantia exata de 17 comparações em toda consulta em árvore de Java.
Considere a tarefa inteira
Construir um conjunto adicional custa tempo e memória. Para poucos elementos ou uma única consulta, a lista original pode ser suficiente. Para verificações repetidas de pertinência, um conjunto reutilizável frequentemente elimina o principal custo. Comece pelo comportamento necessário e depois examine as operações repetidas com mais frequência.
Principais conclusões
- As designações de crescimento descrevem como o custo aumenta, não um número medido de segundos.
ArrayListoferece acesso rápido por índice, mas buscas e alterações no início são lineares.- Consultas baseadas em hash são constantes em média com códigos de dispersão adequados; consultas em árvores são logarítmicas.
- Construa um conjunto de pertinência uma vez para substituir buscas repetidas em listas.
- Inclua o tempo de preparação e a memória ao comparar soluções completas.
6.2 Selecione uma coleção que atenda à tarefa
A coleção adequada mantém as informações de que o programa precisa e facilita a expressão de suas principais perguntas. Decida as regras dos dados antes de escolher o nome de uma classe conhecida.
Pergunte o que identifica um item
| Necessidade principal | Escolha inicial | Exemplo |
|---|---|---|
| Encontrar um valor por uma chave separada | Map | Código de produto associado a preço |
| Testar pertinência sem duplicatas | Set | Nomes de usuário ocupados |
| Manter posições, ordem ou itens repetidos | List | Uma playlist que repete músicas |
| Manter um número fixo de posições | Vetor | Doze medições mensais de precipitação |
Um double[12] pode armazenar a precipitação em milímetros quando cada posição corresponde a um mês conhecido. Um mapa cujas chaves são apenas as posições 0, 1, 2 e assim por diante acrescenta uma camada que uma lista ou um vetor já fornece.
Escolha a ordem necessária
Para mapas e conjuntos, use HashMap ou HashSet quando nenhuma ordem for necessária, LinkedHashMap ou LinkedHashSet para ordem de inserção e TreeMap ou TreeSet para chaves ou elementos ordenados. Para uma lista de uso geral, comece com ArrayList.
Contagens de palavras exibidas em ordem alfabética combinam com um TreeMap<String, Integer>. Uma lista de marcadores distintos na ordem em que foram vistos pela primeira vez combina com LinkedHashSet<String>. Músicas repetidas exigem uma lista, mesmo que também estejam armazenadas em outro lugar em um conjunto: descartar repetições alteraria a playlist.
Combine coleções quando os dados tiverem camadas
Alunos por curso podem ser representados por Map<String, List<String>>; cada valor é uma lista ordenada de matrículas. Marcadores por artigo podem ser representados por Map<String, Set<String>>; cada artigo recebe marcadores distintos. Uma tabela de classificação pode ser uma List<Player> ordenada pela comparação natural do jogador.
As escolhas externas e internas respondem a perguntas diferentes. Se os cursos devem ser listados em ordem alfabética e os alunos mantidos em ordem de matrícula, use um TreeMap por fora e uma lista por dentro. Ordenar as chaves não ordena as listas. Se registros de matrícula duplicados devem ser ignorados, use um conjunto para os grupos internos.
Mantenha dados relacionados juntos
Duas listas paralelas, uma de nomes e outra de números de telefone, dependem de posições correspondentes. Remover um nome sem seu número desfaz todos os pares seguintes. Se os nomes identificarem pessoas de forma única, um mapa pode guardar a associação. Se nomes se repetirem ou vários campos pertencerem a uma pessoa, mantenha objetos de pessoas em uma lista ou indexe-os por um ID único.
Pesquisar uma lista repetidamente por um campo é outro sinal de que vale considerar um mapa como índice. Mantenha também a lista se a ordem de exibição e as entradas repetidas importarem, mas atualize as duas estruturas em conjunto quando dados forem adicionados ou removidos.
Verifique as regras dos elementos e o tipo declarado
Use uma declaração com interface, como Map<String, Double> prices = new HashMap<>();, para que quem usa o mapa dependa das operações necessárias. Coleções baseadas em hash precisam de uma igualdade adequada e de códigos de dispersão compatíveis para chaves ou elementos personalizados. Coleções em árvore com comportamento padrão precisam de uma comparação natural que distinga exatamente os valores que a coleção deve manter. Essas regras fazem parte de garantir que a coleção escolhida represente os dados pretendidos.
Principais conclusões
- Escolha mapas para consultas por chave, conjuntos para pertinência e listas para posições ou repetições.
- Vetores podem conter um número fixo de posições, inclusive com valores primitivos.
- Escolha deliberadamente entre ordem de inserção e ordem classificada.
- Coleções aninhadas permitem que as chaves externas e os grupos internos sigam regras diferentes.
- Mantenha campos relacionados juntos e atualize vários índices por meio de métodos compartilhados.
- Ajuste as regras de igualdade e comparação aos valores que a coleção deve manter.
Exercícios resolvidos de HashMaps e coleções em Java
1Acompanhe um mapa de estoque do armazenamento à consulta
13 passos
- 1IntroduçãoComece com uma pergunta sobre um produto
Um programa de estoque precisa responder: “Quantas pastas estão disponíveis?”. Um mapa usa o nome do produto como chave e sua quantidade como valor. Acompanhe um mapa durante uma substituição, uma consulta a uma chave ausente e uma limpeza. Depois examine por que uma chave personalizada pode falhar mesmo quando seus campos parecem corretos. Cada consulta depende do que Java considera a mesma chave.
- 2ExplicaçãoCrie uma associação por chave
Crie
HashMap<String, Integer> stock = new HashMap<>();.Stringdescreve as chaves;Integerdescreve os valores. O mapa usa tipos de referência, portantointnão pode ser o argumento de tipo do valor. Java empacota um literal como6quandostock.put("folder", 6)o armazena. O diamante à direita permite que Java infira os dois tipos. - 3ExemploSubstitua uma quantidade
Execute estas atualizações em ordem:
stock.put("folder", 6); stock.put("clip", 11); Integer old = stock.put("folder", 8);A última chamada encontra a chave existente de pasta, armazena
8e retorna6paraold. Ainda há duas chaves. Um mapa registra o valor mais recente de uma chave; ele não soma quantidades automaticamente nem mantém um histórico delas. - 4DesafioLeia sem inserir
Quais são os valores de
nestock.size()depois desta leitura? O mapa ainda contém pasta 8 e clipe 11.int n = stock.getOrDefault("tape", 0);---reveal---
né0, e o tamanho permanece2. O valor padrão é um resultado para uma chave ausente, não uma entrada inserida. Ler comget("tape")retorna null, que não pode ser desempacotado em umint. - 5ExplicaçãoLeia os pares juntos
Um laço sobre entradas fornece cada chave e seu valor juntos:
for (Map.Entry<String, Integer> e : stock.entrySet()) { System.out.println(e.getKey() + ": " + e.getValue()); }Importe
java.util.Map. O laço pode mostrar as duas associações sem umgetseparado. Se apenas um total for necessário, percorrastock.values()e some as quantidades; quantidades repetidas ainda contribuem separadamente. - 6Ideia-chaveNão presuma qual será a primeira entrada
A saída pode listar pasta antes de clipe ou clipe antes de pasta. HashMap não garante nenhuma das duas ordens. Um resultado como uma soma não é afetado, mas uma regra de “manter a primeira pontuação empatada” pode depender do percurso. Escolha
LinkedHashMappara ordem de inserção ouTreeMappara chaves ordenadas e defina uma regra explícita para máximos empatados quando o vencedor precisar ser previsível. - 7ExemploExclua durante o percurso
Suponha que pasta agora seja 0 e clipe seja 11. Remova quantidades zero com um iterador:
Iterator<Map.Entry<String, Integer>> it = stock.entrySet().iterator(); while (it.hasNext()) { if (it.next().getValue() == 0) { it.remove(); } }O iterador remove sua entrada atual e continua com segurança. Chamar
stock.removedurante um percurso for-each pode, em vez disso, provocarConcurrentModificationException. - 8DesafioSepare uma cópia das chaves
Antes da limpeza,
keysé criada comnew ArrayList<>(stock.keySet()). Sekeys.remove("folder")for chamado, o que acontece com o mapa de estoque?---reveal---
O mapa mantém sua associação para pasta.
keysé uma lista separada das chaves que existiam quando ela foi copiada. Remover do própriostock.keySet()removeria a entrada do mapa, pois esse objeto é uma visão vinculada. - 9ExemploExperimente uma chave personalizada
Imagine que
Bintenha os camposrowecolumne nenhuma sobrescrita de igualdade. Armazene um rótulo usandonew Bin(3, 4)e depois consulte-o usando outronew Bin(3, 4). A consulta retorna null. São dois objetos diferentes, e oObject.equalsherdado usa identidade. Valores de campos correspondentes ainda não foram transformados em uma regra de correspondência de chaves. - 10ExplicaçãoFaça a igualdade e o hash concordarem
Para definir a identidade de um compartimento pelas coordenadas, sobrescreva
equals(Object other)para comparar linha e coluna e sobrescrevahashCode()usando os mesmos campos, por exemplo,Objects.hash(row, column). Coordenadas iguais devem produzir códigos de dispersão iguais. Um código de dispersão correspondente, por si só, não estabelece igualdade; a verificação de igualdade ainda distingue chaves com coordenadas diferentes. - 11DesafioIdentifique uma sobrecarga
Uma classe define
public boolean equals(Bin other)ehashCode()a partir de suas coordenadas. Por que uma consulta com um compartimento separado, aparentemente igual, ainda pode falhar?---reveal---
O parâmetro deve ser
Objectpara sobrescrever o método de igualdade de Java. O método com parâmetro Bin é uma sobrecarga, deixando em vigor a igualdade por identidade herdada. Adicionar@Overridea essa assinatura incorreta faz o compilador revelar o erro. - 12DesafioCorrija um projeto com chave mutável
Uma chave de compartimento usa linha e coluna em ambos os métodos de igualdade. O programa altera sua linha enquanto ela está armazenada e depois não consegue encontrar seu rótulo. Como ele deve atualizar a localização e depois remover rótulos vazios com segurança durante o percurso?
---reveal---
Remova a associação antes de alterar a chave e depois insira-a novamente. Para a limpeza durante o percurso, use o próprio método de remoção do iterador de entradas. Uma identidade de chave estável e um percurso seguro resolvem partes diferentes dessa atualização.
- 13RecapitulaçãoMantenha uma lista de verificação para atualizar mapas
Para uma consulta a uma chave ausente, decida se um valor padrão ou uma verificação explícita de ausência é adequado à tarefa. Para um laço, decida se a ordem importa e se chaves serão removidas. Para uma chave personalizada, verifique a assinatura exata de
equals(Object), os campos correspondentes usados no hash e a estabilidade da identidade. Essas verificações localizam causas diferentes do mesmo sintoma: uma associação que o programa não consegue usar como esperado.
2Construa informações de participação à medida que os registros chegam
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoTransforme registros recebidos em respostas úteis
- 2ExemploInicie uma contagem de sessões
- 3ExemploDistinga sessões distintas de registros
- 4DesafioCorrija uma contagem reiniciada
- 5ExplicaçãoCrie um grupo uma única vez
- 6ExemploAcompanhe a referência interna
- 7DesafioEncontre o erro de grupo compartilhado
- 8ExplicaçãoIndexe por uma chave de identificação
- 9Ideia-chaveAltere um objeto em vários lugares
- 10DesafioMantenha a remoção consistente
- 11DesafioCombine contagens com membros distintos
- 12RecapitulaçãoVerifique uma primeira entrada e uma repetição
3Compare dois grupos de participantes
9 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoPergunte quem participou, não quantas visitas houve
- 2ExemploElimine leituras repetidas
- 3DesafioPare na primeira entrada repetida
- 4ExemploMantenha apenas os membros comuns
- 5ExplicaçãoEscolha a direção da diferença
- 6DesafioTeste um grupo selecionado
- 7DicaEscolha uma ordem útil para o relatório
- 8DesafioFaça um relatório ordenado de ausências
- 9RecapitulaçãoInterprete o receptor como o grupo inicial
4Interprete declarações e cópias de coleções
10 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoInterprete os dois lados da declaração
- 2ExplicaçãoDeclare o que quem chama o método precisa
- 3ExemploUse um parâmetro mais abrangente para leitura
- 4DesafioIdentifique a causa do método ausente
- 5ConexãoEscolha o significado do conteúdo
- 6ExemploAcompanhe a remoção de inteiros
- 7DesafioCopie antes de ordenar
- 8Ideia-chaveDistinga alterações em objetos de alterações na lista
- 9DesafioPasse a visão correta do mapa
- 10RecapitulaçãoVerifique tipo, operação e objeto
5Construa uma classificação que preserve os empates corretos
15 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoEscolha o que vem primeiro
- 2ExemploOrdene a mesma lista
- 3ExplicaçãoExamine o primeiro caractere diferente
- 4DesafioUse uma ordem fornecida
- 5ExplicaçãoDê uma ordem natural a uma classe
- 6ExemploEvite um falso empate numérico
- 7DesafioInverta o campo numérico
- 8ExemploDesfaça apenas empates reais
- 9ExemploAcompanhe a classificação
- 10DesafioVeja o que um conjunto em árvore mantém
- 11Ideia-chaveFaça a ordenação corresponder à identidade
- 12ConexãoVerifique a chave de um mapa ordenado
- 13DesafioMantenha todos os resultados em uma lista classificada
- 14DicaFaça a regra funcionar para três elementos
- 15RecapitulaçãoVerifique uma comparação em dois contextos
6Escolha estruturas para uma lista de alunos de cursos
10 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoListe as perguntas que o programa faz
- 2ExemploObserve a busca dentro do laço
- 3ExplicaçãoPrepare a verificação de pertinência uma única vez
- 4DesafioCompare entradas em crescimento
- 5ExemploMantenha registros de matrícula repetidos
- 6ExplicaçãoEscolha a ordem externa e a interna
- 7DesafioCorrija a regra errada para duplicatas
- 8DicaConsidere o custo da ordem necessária
- 9DesafioCombine o projeto final
- 10RecapitulaçãoEscolha o comportamento antes de medir a velocidade
Questões de HashMaps e coleções em Java
Conjunto 1: Use interfaces e ordene dados10 Questões de Prática
Questão 1 de 10
Set<String> codes = new HashSet<>();, qual é o tipo declarado de codes?Mostrar respostaOcultar resposta
Set<String>, portanto chamadas por meio de codes são verificadas em relação a essa interface. O lado direito constrói um objeto HashSet. Confundir a classe do objeto com o tipo declarado da variável pode ocultar por que um método específico da classe não está disponível por meio de uma variável de interface.Questão 2 de 10
a.compareTo(b)?Mostrar respostaOcultar resposta
Questão 3 de 10
List<Integer> mutável começa como [4, 8, 12]. Ela executa remove(1). O que permanece?Mostrar respostaOcultar resposta
Questão 4 de 10
"zebra", "Apron", "18", "3", "ant"?Mostrar respostaOcultar resposta
Questão 5 de 10
Collection<String>. Quem o chama tem Map<String, String> labels e quer que o método processe cada valor de rótulo. O que deve ser passado?Mostrar respostaOcultar resposta
Collection<String> que contém os valores dos rótulos. O próprio mapa não é uma Collection, e seu conjunto de entradas contém entradas em vez de cadeias de caracteres. Passar o iterador forneceria um objeto de percurso em vez do tipo de coleção exigido pelo parâmetro.Questão 6 de 10
(int) (this.price - other.price). O que dá errado para os preços 6,8 e 6,3?Mostrar respostaOcultar resposta
Double.compare preserva a ordem correta.Questão 7 de 10
compareTo deve fazer em seguida?Mostrar respostaOcultar resposta
Questão 8 de 10
Ticket mutável. Um segundo ArrayList é copiado dela. O programa altera o rótulo do ticket por meio da cópia e depois limpa a cópia. O que a lista original contém?Mostrar respostaOcultar resposta
Questão 9 de 10
Mostrar respostaOcultar resposta
Questão 10 de 10
Reading.equals usa o ID da estação e a temperatura, mas sua comparação natural usa apenas a temperatura. Um TreeSet padrão recebe A com 16, B com 16 e depois C com 12. Qual é seu tamanho e quais IDs são mantidos?Mostrar respostaOcultar resposta
Conjunto 2: Leia e atualize mapas de forma confiável10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
HashMap<String, Integer> vazio recebe put("brush", 5) e depois put("brush", 14). Qual é seu tamanho e qual é o valor de "brush"?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
"tray". O que acontece quando int n = map.get("tray"); é executado?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
equals correto. Como devem ser seus códigos de dispersão?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
"beam" → 9. O programa executa Integer old = map.put("beam", 13); e depois Integer removed = map.remove("beam");. Quais são old, removed e o tamanho final?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
entrySet() e deve excluir cada entrada com valor zero. Como ele deve remover a entrada durante o percurso?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Cell define equals(Cell other) e um hashCode baseado em campos. Células separadas com campos iguais não correspondem como chaves de HashMap. Que alteração de método corrige o erro de igualdade?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
"ink" → 4 e "paper" → 0. keys é um novo ArrayList copiado de seu conjunto de chaves. O programa remove "ink" de keys, remove "paper" pela visão do conjunto de chaves do mapa e depois dobra todos os valores restantes do mapa. O que resta no mapa?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Location usam uma coordenada mutável. Uma chave é armazenada e sua coordenada é alterada enquanto ela está armazenada; agora sua associação não é encontrada na consulta. Que sequência de atualização o projeto deve usar para evitar essa falha?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 3: Construa contagens e compare grupos10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
!seen.add(n). Qual número é informado?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Device é armazenado em uma lista e em um mapa por ID. Ele é recuperado do mapa e depois seu campo de estado é alterado. Qual estado a referência armazenada na lista apresenta?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
C.removeAll(B). O que C contém?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
"north" → 4, "south" → 2 e "west" → 3. Quantas chaves distintas ele contém?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
"cedar". O que outra chamada a add("cedar") retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
"red", "gold", "red", "blue", "gold", "red" usando counts.put(word, counts.getOrDefault(word, 0) + 1). Quais são a contagem de red e o tamanho do mapa?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
groups.put(team, new ArrayList<>()); seguido de groups.get(team).add(name);. Uma equipe recebe Omar, Pia e depois Ren. O que permanece sob essa equipe?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
"Morning" e "Evening". O programa adiciona "Lee" por Morning, depois substitui a associação de Evening por uma nova lista e adiciona "Jo" por Evening. Quais são os grupos finais?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
retainAll(B). D é copiado de B e executa removeAll(C). Quais são D e o resultado de A.containsAll(C)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 4: Identifique o comportamento de coleções10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
"pending" explicitamente associada a null. O que getOrDefault("pending", 20) retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Set.of("draft", "final", "draft") é avaliado?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
"Ari Chen" são inseridos, e o primeiro não pode mais ser recuperado por esse nome. Qual projeto preserva diretamente ambos para consulta individual?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Collections.reverse(list), qual é seu conteúdo?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
"Support". O programa avalia List<String> result = groups.getOrDefault("Support", new ArrayList<>()); e depois adiciona "Nia" a result. O que uma chamada posterior a groups.get("Support") retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
ScoreKey usa equipe e pontos; sua comparação natural usa apenas pontos. Um TreeMap padrão recebe a chave East-30 com valor "old", West-30 com valor "new" e depois North-18 com valor "low". Qual é seu tamanho e qual valor é encontrado usando East-30?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
addAll(B) e depois removeAll(A). Qual é U e algum dos originais mudou?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 5: Combine consulta, agrupamento e ordem10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
map.values() produz?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
get. Qual correção completa preserva os requisitos?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Agrupamento
C
Chave mutável
Classe empacotadora
Integer como tipo de valor porque int não pode aparecer como argumento de tipo genérico.Classe HashMap
HashMap<String, Integer> pode consultar a contagem atual de um produto sem usar uma posição em uma lista.Classe HashSet
HashSet<String> pode acompanhar nomes já processados enquanto um programa lê uma sequência de entrada maior.Classe LinkedHashMap
LinkedHashMap ordenado por inserção.Classe LinkedHashSet
LinkedHashSet perde as repetições, mantendo a ordem em que os marcadores apareceram pela primeira vez.Classe TreeMap
firstKey().Classe TreeSet
Coleção aninhada
Coleção não modificável
List.of deve ser copiada antes da ordenação, mas um objeto mutável armazenado não é congelado por essa lista.Comparador
String.CASE_INSENSITIVE_ORDER ordena uma lista sem alterar as letras maiúsculas e minúsculas armazenadas em cada cadeia.Conjunto
Consistência com equals
Consulta por chave
Contrato do código de dispersão
equals retornem códigos de dispersão iguais, permitindo colisões para objetos diferentes.x e y tanto no teste de igualdade quanto no método de código de dispersão.Cópia superficial
Critério de desempate
Custo de preparação
D
Desempacotamento
int o resultado de uma consulta Integer a uma chave ausente falha porque o null retornado não pode ser desempacotado.Diferença de conjuntos
E
Empacotamento automático
12 em um mapa de valores Integer empacota automaticamente esse número para armazenamento.Encapsulamento
addBook os atualize em conjunto, em vez de quem chama alterá-los.Escolha da coleção
Estouro de inteiro
Integer.compare evita a inversão de sinal que a subtração pode causar.I
Identificador único
Igualdade de conteúdo
equals(Object).Igualdade por identidade
Object.Implementação
HashMap e TreeMap implementam Map, mas oferecem garantias diferentes sobre a ordem das chaves.Interface
List<String> pode receber um ArrayList ou um LinkedList sem alterar sua assinatura.Interface Collection
Collection<String> e percorrer uma lista ou um conjunto.Interface Comparable
compareTo com tipo específico.Comparable<Member> para que a ordenação de listas ordene suas instâncias por altura.Interface Map.Entry
Interseção
retainAll remove do receptor os valores não compartilhados.Item distinto
"sun rain sun" contém duas chaves de palavras distintas, mas registra três ocorrências.Iterador
hasNext(), next() e o remove() do iterador para excluir quantidades zero.Í
Índice
L
Lista
Listas paralelas
M
Mapa
Método compareTo
Método getOrDefault
Método putIfAbsent
putIfAbsent pode garantir que sua chave tenha uma lista sem substituir uma lista existente.Modificação estrutural
N
Normalização de chaves
O
Ocorrência duplicada na entrada
add retorna falso.Ordem de iteração
Ordem natural
"20" e "3" coloca "20" primeiro porque os caracteres iniciais decidem sua ordem.Ordem por unidades de código dos caracteres
"7", "Bee" e "ant", a ordem natural de cadeias coloca o algarismo antes das letras.Ordenação estável
Ordenação na própria lista
Collections.sort(values), a variável de lista existente disponibiliza seus elementos na nova ordem.P
Par chave–valor
"pen" → 18 associa um nome de produto à quantidade disponível no momento.Parâmetro de tipo de interface
Map<String, Integer> enquanto quem o chama escolhe armazenamento baseado em hash ou em árvore.Pertinência
contains usando a regra de correspondência desse conjunto.R
Referência compartilhada
S
Sintaxe de diamante
HashMap<String, Integer> m = new HashMap<>();, o diamante evita repetir os dois tipos.Sobrecarga
remove(1) seleciona a remoção por índice, enquanto remove(Integer.valueOf(1)) seleciona a remoção por valor.Soma acumulada
Subconjunto
a.containsAll(b) testa se b está contido em a.T
Tabela de consulta
Tabela de frequências
Tempo constante
ArrayList não exige percorrer todas as posições anteriores dessa lista.Tempo linear
Tempo logarítmico
Tipo declarado
ArrayList armazenado em uma variável List não disponibiliza ensureCapacity por meio dessa variável.Transitividade
Truncamento
U
União
addAll de Java a forma alterando o conjunto receptor.V
Vetor
double[12] pode dar a cada mês uma posição para sua medição de precipitação em milímetros.Visão de coleção
- 1Primeiros programas em Java
- 2Condições e laços em Java
- 3Métodos em Java
- 4Listas e vetores em Java
- 5Classes e objetos em Java
- 6Objetos e referências em Java
- 7HashMaps e coleções em Java
- 8Herança, interfaces e polimorfismo em Java
- 9Exceções em Java
- 10Pacotes e testes unitários em Java
- 11Genéricos e expressões lambda em Java
Sobre esta aula
Crie seus próprios Materiais de Estudo
Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.