Impressão de HashMap

Pessoal, boa noite!

Estou com uma duvida em relação a listagem do HashMap, segue o codigo, consigo adicionar e remover:

import java.util.*;

public class HashMaap implements Agenda {

private Map<Contato,String> contatos = new HashMap<>();

public boolean adicionar(String nome, String telefone){
    Contato contato = new Contato(nome);
    for(Contato c : this.contatos.keySet()){
        contatos.containsKey(telefone);
        contatos.containsValue(nome);
        if(c.equals(contato)){
           return contatos != null;
        }
    }
    return contato.getTelefone().add(telefone);
}

public boolean remover(String nome, String telefone){
	Contato c = new Contato(nome);
	for(Contato i: this.contatos.keySet()){
       if(i.equals(c)){
           i.getTelefone().remove(telefone);
           if(i.getTelefone().isEmpty()){
               this.contatos.remove(i);
           }
       }      
   }
   return false;
}

public Collection<Contato> getContatos(){
	return (Collection<Contato>) this.contatos;
}

}

Alguem poderia dizer o que está errado?

Qual é a mensagem de erro que aparece? Qual o problema/erro?

Aparece a seguinte mensagem:

Exception in thread “main” java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.Collection
at parcialAgenda.HashMaap.getContatos(HashMaap.java:35)
at parcialAgenda.AppAgenda.listar(AppAgenda.java:64)
at parcialAgenda.AppAgenda.main(AppAgenda.java:26)

Você esta tentando converter HashMap pra Collection, a pergunta é, pq?

O que você esta colocando no valor do map?

Qual seria a melhor forma de listar?

Da até para diminuir o método abaixo usando lambda do java 8

Map<String, String> map = new HashMap<>();

...
for(Map.Entry<String, String> entry :map.entrySet())
{
	System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}

Map trabalha com chave e valor
Através de uma chave encontramos o seu valor, normalmente um id/código ou algo que seja único, que não vá se repetir nos outros objetos.

Você fez um cenário que é raro encontrar, esta utilizando a classe Contato como chave para chegar a um valor String, por isso lhe pergunto de novo, o que seria a sua String que esta no map?

Segue todas minhas classes, estava com ArrayList mas gostaria de mudar para HashMap

package parcialAgenda;

import java.util.Collection;

public interface Agenda {

public boolean adicionar (String nome, String telefone);

public boolean remover (String nome, String telefone);

public Collection<Contato> getContatos();

}


import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;

public class Contato {

private String nome;
private Set<String> telefone;

public Contato(String nome) {
	this.nome = nome;
	this.telefone = new HashSet<>();
}

//Gerar os gets e sets, equals e HashCode

public String getNome() {
	return nome;
}

public void setNome(String nome) {
	this.nome = nome;
}

public Set<String> getTelefone(){
	return telefone;
}

public int hashCode() {
	return this.nome.hashCode();
}

public boolean equals (Object obj) {
	if (this==obj) {
		return true;
	}
	if (obj==null) {
		return false;
	}
	if (getClass()!=obj.getClass()) {
		return false;
	}
	final Contato other = (Contato) obj;
	if(!Objects.equals(this.nome, other.nome)) {
		return false;
	}
	return true;
}

}


package parcialAgenda;

import java.util.Scanner;

public class AppAgenda {

private static Agenda agenda = new HashMaap();

public static void main(String[] args) {

	Scanner teclado = new Scanner (System.in);
	
	int opcao = 0;
	
	do {
		System.out.println("####Aplicativo Agenda####");
		System.out.println("1 - Adicionar um telefone");
		System.out.println("2 - Remover um telefone");
		System.out.println("3 - Listar contatos");
		System.out.println("4 - Sair");
		opcao = Integer.valueOf(teclado.nextLine());
		
		switch (opcao) {
		case 1: adicionar(teclado); break;
		case 2: remover(teclado); break;
		case 3: listar(); break;
		}
		
	}while (opcao != 4);
	teclado.close();
	
}

public static void adicionar (Scanner teclado) {
	System.out.println("Informe o nome do contato: ");
	String nome = teclado.nextLine();
	
	System.out.println("Informe o novo telefone");
	String telefone = teclado.nextLine();
	
	if (agenda.adicionar(nome, telefone)) {
		System.out.println("Adicionado com Sucesso!");
	}else {
		System.out.println("Telefone já existe!");
	}
}

public static void remover (Scanner teclado) {
	System.out.println("Informe o nome do contato: ");
	String nome = teclado.nextLine();
	
	System.out.println("Informe o telefone do contato: ");
	String telefone = teclado.nextLine();
	
	if(agenda.remover(nome, telefone)) {
		System.out.println("Removido com sucesso!");
	}else {
			System.out.println("Contato/Telefone não existem!");
		}
	
}

public static void listar() {
	for (Contato c: agenda.getContatos()) {
		System.out.println(c.getNome()+": "+c.getTelefone());
	}
}

}


package parcialAgenda;

import java.util.*;

public class HashMaap implements Agenda {

private Map<Contato,String> contatos = new HashMap<>();

public boolean adicionar(String nome, String telefone){
    Contato contato = new Contato(nome);
    for(Contato c : this.contatos.keySet()){
        contatos.containsKey(telefone);
        contatos.containsValue(nome);
        if(c.equals(contato)){
           return contatos != null;
        }
    }
    return contato.getTelefone().add(telefone);
}

public boolean remover(String nome, String telefone){
	Contato c = new Contato(nome);
	for(Contato i: this.contatos.keySet()){
       if(i.equals(c)){
           i.getTelefone().remove(telefone);
           if(i.getTelefone().isEmpty()){
               this.contatos.remove(i);
           }
       }      
   }
   return false;
}

public Collection<Contato> getContatos(){
	return (Collection<Contato>) this.contatos;
}	

}

Você tentou o código que postei?
Se sim, colocou ele a onde?

Estou começando agora com Java.
Não testei, vou testar.
Entendeu o código?

HashMap não é filha de Collection. Por isso quando você tenta fazer o cast para (Collection<Contato>) dá erro.

Sugestão para a sua função…

public Map<Contato,String> getContatos() {
	return Collections.unmodifiableMap(this.contatos);
}

Collections.unmodifiableMap é uma função que vai retornar uma referencia para o seu Map mas que não deixará outras classes de fora alterar os valores nela, apenas será possível fazer leitura. Talvez isso seja útil pra vc, da uma olhada.

Sim, usar <Objeto, String> não é muito normal, da uma revisada nisso.

1 curtida

Então deveria colocar <String,String>?

La vai a pergunta de novo, o que você esta passando como valor do map?
O “certo” seria inverter o cenario, usar <String,Contato>, mas depende do que você quer e da sua ideia

Fazer Map<String,Contato> seria, por exemplo, colocar String = ID do contato e Contato seria o objeto em si com todos os dados.

Seria algo como:
Map<ID, Objeto>
458 - Contato1
741 - Contato2
123 - Contato3
Etc…

Você iria trabalhar com o Map dizendo “mapa, me retorna o objeto da chave 741”, o Map te retorna o objeto Contato2 e ai você faria as coisas necessárias.
mapaContatos.get(“741”);

Porque vc estaria usando o objeto Contato como chave? E o que vc iria retornar nessa String? Qual era seu objetivo?

Entendi, vou fazer um teste, vou alterar o código, e retorno

Se quer retornar todos os contatos dentro de seu Map, faça assim:

public Collection<Contato> getContatos(){
	return contatos.values();
}

É importante consultar a documentação para aprender como utilizar as classes:
https://docs.oracle.com/javase/10/docs/api/index.html?java/util/Map.html

2 curtidas

Exato! Ai da até para converter o Map em List caso precise.

List<Contato> contatos = new ArrayList<>(contatos.values());
1 curtida