1
resposta

HashSet x ArrayList

Olá pessoal, tudo bem?

Tenho uma dúvida quanto a comparação da velocidade do HashSet e ArrayList para 02 casos que fiz algumas experimentações:

  1. Busca de um objeto único em uma collection muito grande (muitos objetos armazenados) utilizando método contains();
  2. Busca de vários objetos em uma collection grande (muitos objetos armazenados) utilizando método contains();

Nesses 02 cenários fiz a comparação de tempo utilizando HashSet e ArrayList e no cenário 01 o ArrayList foi mais rápido e no cenário 02 o HashSet foi bem mais rápido.. O HashSet não deveria ser mais rápido nos 02 cenários considerando a tabela de espalhamento?

Segue o código abaixo que utilizei:

Cenário de busca de vários objetos em loop:

public static void main(String[] args) {
    Set<Aluno> alunos = new HashSet<Aluno>();
    long timeIni = System.currentTimeMillis();
    for (int i = 1 ; i <= 50000; i++) {
        alunos.add(new Aluno("Aluno"+i,i));
    }

    for (Aluno aluno : alunos) {
        alunos.contains(aluno);
    }
    long timeFim = System.currentTimeMillis();
    long time = timeFim - timeIni;
    System.out.println(time);
}

Cenário de objeto único em Collection muito grande:

public static void main(String[] args) {

    Set<Aluno> alunos = new HashSet<Aluno>();
    long timeIni = System.currentTimeMillis();
    for (int i = 1 ; i <= 5000000; i++) {
        alunos.add(new Aluno("Aluno"+i,i));
    }


    boolean conteudo = numeros.contains(new Aluno("Aluno500000", 500000));
    System.out.println(conteudo);

    long timeFim = System.currentTimeMillis();
    long time = timeFim - timeIni;
    System.out.println(time);
}

}

Classe Aluno (objeto utilizado no Set e ArrayList

public class Aluno {

private String nome;
private int matricula;

public Aluno(String nome, int matricula) {
    this.nome = nome;
    this.matricula = matricula;
}

public String getNome() {
    return nome;
}

public int getMatricula() {
    return matricula;
}

@Override
public String toString() {
    return this.getNome();
}

@Override
public boolean equals(Object aluno) {
    Aluno outroAluno = (Aluno) aluno;
    return this.nome.equals(outroAluno.getNome());
}

@Override
public int hashCode() {
    return String.valueOf(this.getMatricula()).hashCode();
}
1 resposta

Oie Marcus, tudo bem contigo?

Fiz o mesmo experimento que você, usando exatamente o mesmo código que você mandou aqui e no meu ambos o HashSet foi mais rápido.

1º Cenário:

Código:

        Set<Aluno> alunos = new HashSet<Aluno>();
//        ArrayList<Aluno> alunos = new ArrayList();


        long timeIni = System.currentTimeMillis();

        for (int i = 1 ; i <= 50000; i++) {
            alunos.add(new Aluno("Aluno"+i,i));
        }

        for (Aluno aluno : alunos) {
            alunos.contains(aluno);
        }
        long timeFim = System.currentTimeMillis();
        long time = timeFim - timeIni;
        System.out.println(time);

Resposta usando HashSet: 32

Usando ArrayList: 5642

2º Cenário:

Código:

        Set<Aluno> alunos = new HashSet<Aluno>();
//       ArrayList<Aluno> alunos = new ArrayList();

        long timeIni = System.currentTimeMillis();
        for (int i = 1 ; i <= 5000000; i++) {
            alunos.add(new Aluno("Aluno"+i,i));
        }
        boolean conteudo = alunos.contains(new Aluno("Aluno500000", 500000));
        System.out.println(conteudo);

        long timeFim = System.currentTimeMillis();
        long time = timeFim - timeIni;
        System.out.println(time);

Resposta usando HashSet: 3156

Usando ArrayList: 3204

Tenta fazer mais um teste, vê se você não acabou se confundindo, pois aqui realmente ambos deram uma performance melhor ao usar o HashSet.

Aguardo uma resposta sua :)