Duvida Arrays.binarySearch()

9 respostas
O

Estou estudando pra certificacao e entrei no topico de busca de Arrays e Collections…Dae apareceu uma duvida.

Ele diz que o metodo retorna um valor positivo ou o valor 0 indicando que a busca foi bem sucessidida e retorna numero negativo indicando pontos de insercao e busca mal sucedida. O que é esse ponto de insercao e como é feito o calculo para retorna-lo? No livro ele diz assim:
(-(ponto de insercao)-1)… eu nao entendi…

Ex: codigo abaixo…

import java.util.*;
public class TestePessoas {

	public static void main(String[] args) {

		Pessoa[] p = {new Pessoa("diego",15), new Pessoa("carlos", 20), new Pessoa("jack",24)};
		Arrays.sort(p);

		for (Pessoa pp : p ){
			System.out.print(pp);
		}

		System.out.println("\none" + Arrays.binarySearch(p,new Pessoa("jack",24)));

		System.out.println("Depois");

		Resort r = new Resort();
		Arrays.sort(p,r);
		for (Pessoa pp : p )
			System.out.println(pp + " ");
		System.out.println("\ndiego" + Arrays.binarySearch(p,new Pessoa("diego",15)));

	}

	static class Resort implements Comparator<Pessoa> {

		public int compare(Pessoa p1, Pessoa p2) {
			return p1.getIdade() - p2.getIdade();
		}
	}


}

Porque ele retorna -3 na busca pelo objeto (“diego”,15) sendo que a posicao dele é 0 ?

9 Respostas

ViniGodoy

Ele retorna -3 para indicar que:

  1. Como -3 é um número negativo, o objeto não foi encontrado;
  2. O objeto, se for inserido, deverá ser colocado na posição 3. Isso é o ponto de inserção correto.

Lembrando que binarySearch só pode ser usado em listas ordenadas.

ViniGodoy

Você precisará passar o Comparable também para o método BinarySearch:

Arrays.binarySearch(p,new Pessoa(“jack”,24), new Resort());

A busca binária deve ser feita usando o mesmo Comparable usado na ordenação.

O

ViniGodoy:
Ele retorna -3 para indicar que:

  1. Como -3 é um número negativo, o objeto não foi encontrado;
  2. O objeto, se for inserido, deverá ser colocado na posição 3. Isso é o ponto de inserção correto.

Lembrando que binarySearch só pode ser usado em listas ordenadas.

Só uma dúvida: O equals da classe pessoa está implementado corretamente, para procurar pela idade?

ViniGodoy…

Por favor. Mas pq ele nao acha esse objeto? Se eu alterar o codigo para:

Arrays.binarySearch(p,new Pessoa("carlos",20));

Ele acha,…pq ele deveria colocar o objeto na posicao 3?..ele tem 0,1,2… pela classificacao ele nao iria para a posicao 0?

O

Olha o codigo da Classe Pessoa…

public class Pessoa implements Comparable<Pessoa>{

	private String nome;
	private int idade;

	public Pessoa(String nome, int idade) {
		this.nome = nome;
		this.idade = idade;
	}

	public String getNome() {
		return this.nome;
	}

	public int getIdade() {
		return this.idade;

	}

	public String toString() {

		return "Nome " + getNome() + " Idade : " + getIdade() + "\n";
	}


	public int compareTo(Pessoa p){
		return this.getNome().compareTo(p.getNome());
	}


}

Eu estou usando Comparator…

T

Você não implementou o “equals” (embora isso não seja explicitamente descrito na documentação, ele só irá retornar um valor positivo se a classe implementar “equals” corretamente).

EDIT - falei besteira; não é preciso implementar “equals”. Só olhar o fonte do JDK.

public static <T>
    int binarySearch(List&lt? extends Comparable&lt? super T&gt&gt list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

    private static ><T>
    int indexedBinarySearch(List&lt? extends Comparable&lt? super T&gt&gt list, T key)
    {
	int low = 0;
	int high = list.size()-1;

	while (low &lt= high) {
	    int mid = (low + high) &gt&gt&gt 1;
	    Comparable&lt? super T&gt midVal = list.get(mid);
	    int cmp = midVal.compareTo(key);

	    if (cmp &lt 0)
		low = mid + 1;
	    else if (cmp &gt 0)
		high = mid - 1;
	    else
		return mid; // key found
	}
	return -(low + 1);  // key not found
    }

    private static <T>
    int iteratorBinarySearch(List&lt? extends Comparable&lt? super T&gt&gt list, T key)
    {
	int low = 0;
	int high = list.size()-1;
        ListIterator&lt? extends Comparable&lt? super T&gt&gt i = list.listIterator();

        while (low &lt= high) {
            int mid = (low + high) &gt&gt&gt 1;
            Comparable&lt? super T&gt midVal = get(i, mid);
            int cmp = midVal.compareTo(key);

            if (cmp &lt 0)
                low = mid + 1;
            else if (cmp &gt 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found
    }
O

Thingol…

Mesmo assim nao entendi… desculpe a minha falta de inteligencia…

ViniGodoy

Como eu expliquei ali em cima, você deve estar usando critérios diferentes para a comparação e para a igualdade.

Além disso, quando você não deixa explicito qual comparador usar no binary search, ele vai olhar se a classe pessoa é comparable, e usar a ordem natural da classe pessoa (que deve ser por nome) para fazer a busca, ao invés de usar a ordenação feita pela segunda vez (por idade).

Isso vai mesmo deixar a busca um tanto maluca.

O segredo é usar o mesmo comparator tanto para a ordenação, quanto para o BinarySearch.

Mude o seu segundo binarySearch para:
System.out.println("\ndiego" + Arrays.binarySearch(p,new Pessoa(“diego”,15), r));

Que deve funcionar.

D

Perceba duas observações sobre o código:
1- A implementação de compare() da interface Comparable está implementando uma lógica de classificação alfabética por nome;
2- Na segunda chamada ao método binarySearch, o array foi classificado usando-se um Comparator, mas este não foi informado na chamada do método, o que causa resultados inconsistentes. O código seria então:

Arrays.binarySearch(p,new Pessoa("diego",15), r);

Além disso, como o Thingol mencionou, o método equals() deve ser implementado para a recuperação do objeto correto (senão será fornecida a implementação de Object, que retorna false para instancias diferentes, embora seus conteúdos sejam equivalentes).

O

Eu entendi… mas só pra gerar uma polêmica e sanar a minha duvida…pq que se eu alterar o codigo de :

// que retorna -3 Arrays.binarySearch(p,new Pessoa("diego",15)));
Para

// que retorna 2 Arrays.binarySearch(p,new Pessoa("jack",24));
Ambos estao usando a chamada sem passar o Camparator…

Criado 4 de abril de 2007
Ultima resposta 4 de abr. de 2007
Respostas 9
Participantes 4