Implementar uma classe que simule a classe HasMap

Boa tarde galera, estou tendo dificuldade para implementar esse exercício ele tem que ser sem o uso de HasMap Map e outras colection , devo usar somente classes

        public class principal {
                public static void main(String[] args) {
                     Dicionario dicio = new Dicionario();
                      dicio.setValor(new Chave("um"), new Valor("joão"));
                      dicio.setValor(new Chave("dois"), new Valor(("  pedro")));
                      System.out.println(dicio);
    }  
}

Saida seria:

Um = joão
Dois = pedro 

Meu código

        class Chave{
             .......
              return chave
       }
        class Valor{
            .........
           return valor
      }
      class Dicionario{
        Object chave ;
	    Object valor;
	    Object [] objetos;
	    int qtd;
	   Dicionario(Object chave, Object valor){
		   this.objetos = new Object[10];
		   this.chave = chave;
		   this.valor = valor;
		   this.qtd = 0;
	}
        Dicionario(Object chave, Object valor){
		     this.objetos = new Object[10];
		     this.chave = chave;
		     this.valor = valor;
		     this.qtd = 0;
	   }
	   public void setValor(Object chave, Object valor) {
		    Dicionario dic = new Dicionario(chave,valor);
		    objetos[qtd] = dic;
		    qtd++;	
	}
       public String toString() {	
		   for (int i = 0; i < objetos.length; i++) {
			   System.out.println( objetos[i]);	
		}
		return "";
	}

Minha saida fica

Exception in thread "main" java.lang.NullPointerException

Em vez de ter uma classe Chave e outra Valor, tenha apenas uma para manter a chave e o valor, ex.: ItemDicionario. E na classe Dicionario crie um array de ItemDicionario.

Tenho que manter as classes Chave e Valor separadas.

Olá lucas , vc está falando em extends é isso.

Não. Apenas usar uma classe apenas em vez de duas.

É algum requisito do trabalho mesmo? Se for é muito estranho, pois pensando em OOP, essa classe que sugeri vc criar para armazenar a chave e o valor seria uma entrada de dados do dicionário. Algo mais ou menos assim (a própria implementação de HashMap usa uma classe para guardar a chave e o valor que são adicionados nele):

public class ItemDicionario {
    private Object chave;
    private Object valor;
}

E para ficar melhor, vc poderia fazer com generics em vez de usar Object.

É um trabalho de POO, e pede ainda para usar array, estou com muita dificuldade pra entender esse conceito , não consigo armazer essas duas classes em um array de modo que fiquem as duas em uma posição só do vetor.

Exatamente por se tratar de POO, que indiquei vc criar uma classe para armazenar a chave e o valor das entradas do dicionário. Vai ficar mais POO do que ter duas 2 classes separadas.

Valeu Lucas , consegui implementar como você falou , só falta a ultima implementação para finalizar meu código:

Minha dificuldade é a saida do código metodo toString():

Gostaria de saber se é possivel escolher qual saida terá a classe Valor pelo toString

Meu código:

  main(){
       new Valor("Coord. Disciplina"));
       new Valor(LocalDate.now()));
  }

  class Valor{
      String nome;
      DataTime  now;

      Valor(String nome){
         this.nome = nome;
      }
      Valor(LocalData  now){
            this.now = now;
      }
      public String getValor(){
             return this.nome;
     }
     public  LocalDate getValor(){
           return this.now;
       }
      public String toString(){
        // passando um parametro para imprimir ou this.now ou this.nome
       // seria possível essa implementação?
           // return this.parametro universal para imprimir ou this.nome ou this.now;
     }

Pois estou colocando esses obejetos em uma lista

No toString tu pode referenciar usando o this, veja:

public class Valor {
  String nome;
  DataTime  now;
  
  public Valor(String nome) {
    this.nome = nome;
  }
  
  public Valor(LocalData now) {
    this.now = now;
  }
  
  public String getValor() {
    return this.nome;
  }
  
  public LocalDate getValor() {
    return this.now;
  }
  
  public String toString() {
    return nome + "=" + now;
  }
}

Agora, achei estranho essa classe ter 2 construtores. Ela só poderá ter um valor por vez (ou o nome preenchido ou a data preenchida)?

Outra dúvida é se quiser, por exemplo, armazenar um valor inteiro (int)?

Eu consigo fazer somente com um construtor ?
Uma hora wle receberia String outra hora ele receberia LocalData

Até dá para fazer em um único construtor. Mas qual a ideia dessa classe Valor? Ela poderá guardar apenas valores String ou DateTime mesmo? Qual o objetivo dessa classe no seu programa? Ela servirá para que?

Na claase main fica assim

       public static void main(String[] args) {
                 Dicionario dicio = new Dicionario();
                  dicio.setValor(new Chave("um"), new Valor("joão"));
                  dicio.setValor(new Chave("dois"), new Valor(("  pedro")));
                  dicio.setValor(new Chave("três"), new valor(LocalData.now()))
                  
                  System.out.println(dicio);

A saida seria simular um HasMap;
Vc acha que precisa de construtor para isso?
Agora que observei que é um metodo não é?

    Um = joão
     Dois = pedro
     Três = 2021-08-20
1 curtida

Entendi a ideia. Desse jeito não está ruim não. É que há mais de uma forma de fazer o que vc está querendo. E como a ideia é simular a classe HashMap, já foi me baseando na forma como o próprio HashMap funciona. Porém, para praticar sua lógica de programação, talvez seja melhor tu seguir a ideia que vc teve e, no final, vc irá avaliar se o código ficou bom ou não, onde melhor e pq.

Por curiosidade, como está o código da classe Dicionario?

         Dicionario extends ItemDicionario{
               Valor ....
               Chave .....
               ItemDicionario [] obj ;
               Dicionario( ){
                  Super(valor,chave)
                   This.itemDicionario = new ItemDicionario[ 10];   
               }

                Public  void  setValor(Valor valor, Chave chave){              
                 aqui eu coloco os objetos no vetor porem na hora de imprimir na LocalDataTime e LocalData sai null
}
         }

Esse metodo dentro da classe como implementar ?

       new valor(LocalData.now()))

Acho que vc está causando uma certa confusão nessa classe Dicionario. A relação de herança entre Dicionario e ItemDicionario é estranha.

Trazendo no mundo real, vc acha que seria correto um dicionário SER um item do dicionário? Tente pensar de forma mais simples possível.

Um dicionário seria uma espécie de coleção responsável por armazenar chaves e os valores vinculados à essas chaves. Com isso, não há pq um Dicionario herdar de ItemDicionario.

Sobre a questão das classes Valor e Chave, o problema em manter as duas, na minha visão, seria a dificuldade de manipular, de forma separada, a chave e o valor, que, pelo ponto de vista do dicionario, deveriam ser coisas intimamente ligadas (um valor está ligado à uma chave e vice-e-versa). Por isso sugeri de criar uma única classe para representar a chave/valor.

Tenta montar algo seguindo essas ideias que passei.

Se fosse para esquematizar como seria um dicionário, seria algo mais ou menos assim:

Dicionario = [
  { chave = 1, valor = aaa }, // item do dicionario
  { chave = 2, valor = bbb }, // item do dicionario
  { chave = 3, valor = ccc } // item do dicionario
]

É verdade lucas vou tentar melhorar,.
Seria possivel eu ter uma classe Valor e Classe Chave dentro da Classe Dicionario, pos pelo exercício eu não posso alterar a classe main

  Classe  Main()
        Dicionario dicio = new Dicionario();
        dicio.setValor(new Chave("um"), new Valor("joão"));
         dicio.setValor(new Chave("dois"), new Valor(LocalData.now());

Veja essas duas abordagens:

Vc pode manter na classe Dicionario 2 arrays (um para Chave e outro para Valor), assim:

public class Dicionario {
    private Chave[] chaves;
    private Valor[] valores;
}

Dessa forma, vc teria que fazer o controle nos 2 arrays usando o mesmo índice para garantir que o valor a ser recuperado seja da chave vinculada.


Outra forma seria ter uma classe interna na classe Dicionario para manter a Chave e o Valor, e manter um array dessa classe, assim:

public class Dicionario {
    private Item[] itens;

    static class Item {
        private Chave chave;
        private Valor valor;

        public Item(Chave chave, Valor valor) {
            this.chave = chave;
            this.valor = valor;
        }
    }
}

Dessa forma, vc pode ter um método na classe Dicionario para adicionar valores que, internamente, iria criar o Item e adicionar no array:

public void add(Chave chave, Valor valor) {
    itens[index] = new Item(chave, valor);
    index++;
}

Boa sorte!

Lucas, muito obrigado amigo, vou implementar sua solução.

Apenas repare que passei 2 soluções. Analise e use a que vc achar mais fácil de implementar.

Lucas só mais uma ajuda , nessa caso eu consigo fazer um getValor() para pegar ou valor ou LocalDate quado e percorrer os vetores