Problema com HashMap

7 respostas
T

E ae galera…

Estou com um problema na chave do Map. Eu criei uma classe chamada Bytes, essa ai:

// imports necessarios

public class Bytes implements Comparable {

    private byte[] bytes = new byte[2];

    public Bytes(byte[] bytes) {
        this.bytes = bytes;
    }

    public byte[] getBytes() {
        return bytes;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Bytes)
            return Arrays.equals(bytes, ((Bytes)obj).getBytes());
        else
            return false;
    }

    @Override
    public int hashCode() {
        if (bytes[0] > bytes[1])
            return bytes[0] * bytes[1];
        else
            return bytes[0] + bytes[1];
    }

    @Override
    public String toString() {
        return bytes[0] + "" + bytes[1];
    }

    public int compareTo(Object o) {
        int soma1 = this.bytes[0] + this.bytes[1];
        int soma2 = ((Bytes)o).getBytes()[0] + ((Bytes)o).getBytes()[1];
        return (soma1 - soma2);
    }

}

Ela é o valor da chave. E o valor associado a essa chave é um Integer.

Eu criei essa classe só para armezenar dois bytes que preciso para um algoritmo de compressão.

O HashMap é assim:

HashMap<Bytes, Integer> twoLetters = new HashMap<Bytes, Integer>();

Eu uso ela da seguinte forma:

public static HashMap<Bytes, Integer> readTwoLettersInFile(String wayFile) {
    HashMap<Bytes, Integer> mapTwoLetters = null;
    byte[] stream = new byte[2];
    int size = 0;

    try {
         FileInputStream input = new FileInputStream(wayFile);
         DataInputStream dataInput = new DataInputStream(input);

         mapTwoLetters = new HashMap<Bytes, Integer>();
         Bytes letters = null;

         while ((size = dataInput.read(stream)) != -1) {
               letters = new Bytes(stream);
               Integer count = mapTwoLetters.get(letters);
                
               System.out.println("letters: " + letters);

               if (count == null)
                   mapTwoLetters.put(letters, new Integer(1));
               else
                   mapTwoLetters.put(letters, count + 1);

          }

          dataInput.close();
          input.close();
      }
      catch (FileNotFoundException ex) {
          System.err.println(ex);
      }
      catch (IOException ex) {
          System.err.println(ex);
      }

      return mapTwoLetters;
}

O método acima está em uma classe.

O arquivo teste é o seguinte:

abracadabra
abra
a
barcabraba

Pode ser colocado no bloco de notas e ser salvo como txt.

O problema é quando imprimo os valores no qual só existe a chave 9897 de um total de 8 e inteiros
diferentes para as chaves.

Não entendi porque as chaves são struturas do tipo Set que não permite chaves duplicadas.

Só que comigo obtive oito chaves iguais.

E ainda não encontrei o problema.

Alguém pode me ajudar?

Vlw… Att…

7 Respostas

Rafael_Nunes

Thyaggo:
Não entendi porque as chaves são struturas do tipo Set que não permite chaves duplicadas.
Só que comigo obtive oito chaves iguais.

As chaves são um Set exatamente para isso, para não permitir chaves duplicadas.
Se você está tendo chaves duplicadas, é porque seu método equals(a partir do qual o Set impede a duplicidade) não está se comportando como deveria. Dá uma olhada e faz algunas testes dessa sua implementção do equals.

CintiaDR

Ignore esse post.

thiago.correa

Rafael Nunes:
Thyaggo:
Não entendi porque as chaves são struturas do tipo Set que não permite chaves duplicadas.
Só que comigo obtive oito chaves iguais.

As chaves são um Set exatamente para isso, para não permitir chaves duplicadas.
Se você está tendo chaves duplicadas, é porque seu método equals(a partir do qual o Set impede a duplicidade) não está se comportando como deveria. Dá uma olhada e faz algunas testes dessa sua implementção do equals.

contrato do método equals http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)
e dê uma lida no do hashCode http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#hashCode()

CintiaDR

Olha, pra mim parece certo.

Cria um conjunto de teste menor, com umas três “lidas” e posta tanto o conjunto de teste quanto o resultado da impressão do map, e o código de impressão do mesmo.

CintiaDR

hahahahahahhah Descobri seu problema!

Seguinte, no contrutor de Bytes

public Bytes(byte[] bytes) {
		this.bytes = bytes.clone();
}

Vc não tinha colocado o clone. Todos os arrays de bytes de todas as instancias de ‘Bytes’ estavam vinculadas ao objeto ‘stream’ que é lido do arquivo :roll:

Aliás, faz o toString assim:

public String toString() {
		return new String(bytes) ;

}
Lavieri

seu problema mesmo esta no Construtor da classe… e na forma como vc lê seu input stream…

public Bytes(byte[] bytes) { this.bytes = bytes; }

isso passa uma referencia a uma array, o correto é copiar a array

use a função copia de Arrays para passar este argumento…

while ((size = dataInput.read(stream)) != -1) { letters = new Bytes(stream);

aqui vc nunca cria uma array, portanto, esta passando a mesma referencia de array para dentro do Objeto Bytes … e todos eles vão usar a mesma array, e trocar o valor da array vai fazer o método equals do Set falhar, pois o hashCode vai sair mudando

T

Desculpas por responder só agora. Meu tempo está meio escasso.

Cintia vc estava certa fiz a modificação que postou e o programa rodou blza.

Brigaduuuuuuuu.

Vlw pela ajuda.

Att.

Criado 10 de junho de 2009
Ultima resposta 15 de jun. de 2009
Respostas 7
Participantes 5