Pergunta

Eu estou olhando para implementar um recurso de classificação para a minha candidatura livro de endereços.

Eu quero classificar uma ArrayList<Contact> contactArray. Contact é uma classe que contém quatro campos: nome, número de casa, número de telemóvel e endereço. Quero classificar name.

Como posso escrever uma função de classificação personalizada para fazer isso?

Foi útil?

Solução

Aqui está um tutorial sobre objetos de pedidos:

Embora eu vou dar alguns exemplos, eu recomendaria para lê-lo de qualquer maneira.


Existem várias maneira de classificar uma ArrayList. Se você quiser definir um naturais (padrão) ordenação , então você precisa deixar Contact implementar Comparable . Supondo que você deseja classificar por padrão em name, em seguida, fazer (nullchecks omitidos para simplificar):

public class Contact implements Comparable<Contact> {

    private String name;
    private String phone;
    private Address address;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }

    // Add/generate getters/setters and other boilerplate.
}

para que você pode apenas fazer

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

Collections.sort(contacts);

Se você quiser definir uma ordenação externa controlável (que substitui a ordem natural), então você precisa criar um Comparator :

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Now sort by address instead of name (default).
Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

Você pode até mesmo definir os Comparators no próprio Contact para que você possa reutilizá-los em vez de criá-los sempre que:

public class Contact {

    private String name;
    private String phone;
    private Address address;

    // ...

    public static Comparator<Contact> COMPARE_BY_PHONE = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.phone.compareTo(other.phone);
        }
    };

    public static Comparator<Contact> COMPARE_BY_ADDRESS = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.address.compareTo(other.address);
        }
    };

}

que pode ser usado da seguinte maneira:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Sort by address.
Collections.sort(contacts, Contact.COMPARE_BY_ADDRESS);

// Sort later by phone.
Collections.sort(contacts, Contact.COMPARE_BY_PHONE);

E ao creme a parte de cima, você poderia considerar usar um genérico javabean comparador :

public class BeanComparator implements Comparator<Object> {

    private String getter;

    public BeanComparator(String field) {
        this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
    }

    public int compare(Object o1, Object o2) {
        try {
            if (o1 != null && o2 != null) {
                o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
                o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
            }
        } catch (Exception e) {
            // If this exception occurs, then it is usually a fault of the developer.
            throw new RuntimeException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
        }

        return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));
    }

}

que você pode usar o seguinte:

// Sort on "phone" field of the Contact bean.
Collections.sort(contacts, new BeanComparator("phone"));

(como você pode ver no código, campos possivelmente nulos são já cobertos para evitar NPE de durante a ordenação)

Outras dicas

Além do que já foi publicado, você deve saber que desde Java 8 podemos encurtar o nosso código e escrever assim:

Collection.sort(yourList, Comparator.comparing(YourClass::getFieldToSortOn));

ou desde Lista agora têm método sort

yourList.sort(Comparator.comparing(YourClass::getFieldToSortOn));

Explicação:

Desde Java 8, as interfaces funcionais (interfaces com apenas um método abstrato - eles podem ter mais padrão ou métodos estáticos) pode ser facilmente implementado usando:

Desde Comparator<T> tem apenas um método abstrato int compare(T o1, T o2) é interface funcional.

Então, ao invés de (exemplo de @BalusC resposta )

Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

podemos reduzir esse código para:

Collections.sort(contacts, (Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress());
});

Podemos simplificar este (ou qualquer) lambda saltando

  • tipos de argumentos (Java irá inferir-los com base na assinatura do método)
  • ou {return ... }

Então, ao invés de

(Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress();
}

podemos escrever

(one, other) -> one.getAddress().compareTo(other.getAddress())

Agora também Comparator tem métodos estáticos como comparing(FunctionToComparableValue) ou comparing(FunctionToValue, ValueComparator) que poderíamos usar para criar facilmente comparadores que deve comparar alguns valores específicos de objetos.

Em outras palavras, podemos reescrever o código acima como

Collections.sort(contacts, Comparator.comparing(Contact::getAddress)); 
//assuming that Address implements Comparable (provides default order).

Esta página lhe diz tudo o que você precisa saber sobre ordenação coleções, como ArrayList.

Basicamente, você precisa

  • fazer a sua classe Contact implementar a interface Comparable por
    • criação de um public int compareTo(Contact anotherContact) método dentro dela.
  • Uma vez que você fizer isso, você pode apenas chamar Collections.sort(myContactList);,
    • onde myContactList é ArrayList<Contact> (ou qualquer outra coleção de Contact).

Há uma outra maneira também, que envolve a criação de uma classe Comparator, e você pode ler sobre isso a partir da página vinculada também.

Exemplo:

public class Contact implements Comparable<Contact> {

    ....

    //return -1 for less than, 0 for equals, and 1 for more than
    public compareTo(Contact anotherContact) {
        int result = 0;
        result = getName().compareTo(anotherContact.getName());
        if (result != 0)
        {
            return result;
        }
        result = getNunmber().compareTo(anotherContact.getNumber());
        if (result != 0)
        {
            return result;
        }
        ...
    }
}

BalusC e bguiz já deram respostas muito completas sobre como usar o Java embutido comparadores.

Eu só quero acrescentar que o Google-coleções tem um Encomenda classe que é mais "poderoso" do que os comparadores standard. Pode valer a pena conferir. Você pode fazer coisas legais como a composição ordenações, invertendo-los, ordenando dependendo resultado de uma função para seus objetos ...

aqui é um post que menciona alguns dos seus benefícios.

Você precisa fazer suas aulas de Contato implementar Comparable , e em seguida, implementar o método compareTo(Contact). Dessa forma, o Collections.sort será capaz de classificá-los para você. Per a página que eu ligado a, 'retorna um inteiro negativo, zero, ou um inteiro positivo como este objeto é menor, igual ou maior do que o objeto especificado.' CompareTo

Por exemplo, se você quiser classificar por nome (A a Z), sua classe ficaria assim:

public class Contact implements Comparable<Contact> {

    private String name;

    // all the other attributes and methods

    public compareTo(Contact other) {
        return this.name.compareTo(other.name);
    }
}

Ao usar lambdaj você pode classificar uma coleção de seus contatos (por exemplo, por sua nome) como segue

sort(contacts, on(Contact.class).getName());

ou pelo seu endereço:

sort(contacts, on(Contacts.class).getAddress());

e assim por diante. Mais em geral, oferece uma DSL para acessar e manipular suas coleções de muitas maneiras, como filtrar ou agrupar seus contatos com base em algumas condições, agregar alguns dos seus valores de propriedade, etc.

O Collections.sort é uma implementação de boa sorte. Se você não tem The comparável implementado para contato, você precisará passar em uma implementação Comparador

De nota:

O algoritmo de ordenação é um mergesort modificado (em que a fusão é omitido se o elemento mais alto no baixo sublista é menos do que o elemento mais baixo no alto sublista). Esse algoritmo ofertas garantida n log (n) o desempenho. A lista especificado deve ser modificável, mas não precisa ser redimensionável. Esta implementação despeja a lista especificado em uma matriz, ordena a array, e itera sobre a lista repor cada elemento a partir da posição correspondente na matriz. Isso evita o desempenho log n2 (n) que resultaria da tentativa de ordenar uma lista ligada no lugar.

O merge sort é provavelmente melhor do que a maioria algoritmo de busca que você pode fazer.

Eu fiz isso pelo seguinte maneira. número e nome são duas matrizes. Eu tenho que nome de tipo .Se qualquer mudança acontecer para citar fim arralist então o número arraylist também alterar sua ordem.

public void sortval(){

        String tempname="",tempnum="";

         if (name.size()>1) // check if the number of orders is larger than 1
            {
                for (int x=0; x<name.size(); x++) // bubble sort outer loop
                {
                    for (int i=0; i < name.size()-x-1; i++) {
                        if (name.get(i).compareTo(name.get(i+1)) > 0)
                        {

                            tempname = name.get(i);

                            tempnum=number.get(i);


                           name.set(i,name.get(i+1) );
                           name.set(i+1, tempname);

                            number.set(i,number.get(i+1) );
                            number.set(i+1, tempnum);


                        }
                    }
                }
            }



}

usar este método:

private ArrayList<myClass> sortList(ArrayList<myClass> list) {
    if (list != null && list.size() > 1) {
        Collections.sort(list, new Comparator<myClass>() {
            public int compare(myClass o1, myClass o2) {
                if (o1.getsortnumber() == o2.getsortnumber()) return 0;
                return o1.getsortnumber() < o2.getsortnumber() ? 1 : -1;
            }
        });
    }
    return list;
}

`

e uso: mySortedlist = sortList(myList); Não há necessidade de implementar de comparação na sua classe. Se você quiser ordem inversa 1 swap e -1

Você deve usar a função Arrays.sort. As classes que contêm devem implementar Comparable.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top