Domanda

Sto cercando di implementare una funzione di ordinamento per la mia applicazione della rubrica.

Voglio ordinare un ArrayList<Contact> contactArray. Contact è una classe che contiene quattro campi: nome, numero di casa, numero di cellulare e indirizzo. Voglio ordinare su name.

Come posso scrivere una funzione di ordinamento personalizzata per farlo?

È stato utile?

Soluzione

Ecco un tutorial sull'ordinazione di oggetti:

Anche se fornirò alcuni esempi, consiglierei di leggerlo comunque.


Esistono vari modi per ordinare un ArrayList. Se desideri definire un naturale (predefinito) ordinamento , devi consentire a Contact implementare Comparable . Supponendo che si desideri ordinare per impostazione predefinita su name, quindi fare (controlli null omessi per semplicità):

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.
}

in modo da poterlo fare

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

Collections.sort(contacts);

Se si desidera definire un ordinamento controllabile esterno (che sostituisce l'ordinamento naturale), è necessario creare un 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());
    }
}); 

Puoi anche definire i <=> s nello stesso <=> in modo da poterli riutilizzare invece di ricrearli ogni volta:

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);
        }
    };

}

che può essere utilizzato come segue:

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 per dare un tocco in più, potresti considerare di utilizzare un comparatore javabean generico :

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));
    }

}

che puoi usare come segue:

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

(come vedi nel codice, probabilmente i campi null sono già coperti per evitare NPE durante l'ordinamento)

Altri suggerimenti

Oltre a quanto già pubblicato, dovresti sapere che da Java 8 possiamo abbreviare il nostro codice e scriverlo come:

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

o poiché l'elenco ora ha sort metodo

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

Spiegazione:

A partire da Java 8, le interfacce funzionali (interfacce con un solo metodo astratto - possono avere più metodi predefiniti o statici) possono essere facilmente implementate usando:

Poiché Comparator<T> ha un solo metodo astratto int compare(T o1, T o2) è un'interfaccia funzionale.

Quindi invece di (esempio tratto da @BalusC risposta )

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

possiamo ridurre questo codice a:

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

Possiamo semplificare questa (o qualsiasi altra) lambda saltando

  • tipi di argomenti (Java li inferirà in base alla firma del metodo)
  • o {return ... }

Quindi invece di

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

possiamo scrivere

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

Anche ora Comparator ha metodi statici come comparing(FunctionToComparableValue) o comparing(FunctionToValue, ValueComparator) che potremmo usare per creare facilmente Comparatori che dovrebbero confrontare alcuni valori specifici dagli oggetti.

In altre parole, possiamo riscrivere il codice sopra come

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

Questa pagina ti dice tutto ciò di cui hai bisogno conoscere l'ordinamento di raccolte, come ArrayList.

Fondamentalmente devi

  • fai in modo che la tua classe Contact implementi l'interfaccia Comparable di
    • creando un metodo public int compareTo(Contact anotherContact) al suo interno.
  • Una volta fatto questo, puoi semplicemente chiamare Collections.sort(myContactList);,
    • dove myContactList è ArrayList<Contact> (o qualsiasi altra raccolta di <=>).

C'è anche un altro modo, che prevede la creazione di una classe Comparator, e puoi leggerlo anche dalla pagina collegata.

Esempio:

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 hanno già dato risposte molto complete su come usare i comparatori integrati di Java.

Voglio solo aggiungere che google-collections ha un Ordine che è più " potente " rispetto ai comparatori standard. Potrebbe valere la pena dare un'occhiata. Puoi fare cose interessanti come combinare gli ordini, invertirli, ordinare in base al risultato di una funzione per i tuoi oggetti ...

Qui è un post sul blog che menziona alcuni dei suoi vantaggi.

Devi implementare le tue classi di contatto Comparable , quindi implementa il metodo compareTo(Contact). In questo modo, Collections.sort sarà in grado di ordinarli per te. Per la pagina a cui ho collegato, compareTo 'restituisce un numero intero negativo, zero o un numero intero positivo poiché questo oggetto è minore, uguale o maggiore dell'oggetto specificato.'

Ad esempio, se desideri ordinare per nome (dalla A alla Z), la tua classe sarebbe simile a questa:

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);
    }
}

Utilizzando lambdaj puoi ordinare una raccolta dei tuoi contatti (ad esempio in base al loro nome) come segue

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

o tramite il loro indirizzo:

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

e così via. Più in generale, offre un DSL per accedere e manipolare le tue raccolte in molti modi, come filtrare o raggruppare i tuoi contatti in base ad alcune condizioni, aggregare alcuni dei loro valori di proprietà, ecc.

Collections.sort è una buona implementazione dell'ordinamento. Se non hai implementato il Comparable per Contact, dovrai passare un Implementazione del comparatore

Nota:

  

L'algoritmo di ordinamento è un mergesort modificato (in cui l'unione viene omessa se l'elemento più alto nell'elenco secondario basso è inferiore all'elemento più basso nell'elenco secondario alto). Questo algoritmo offre n prestazioni garantite (n). L'elenco specificato deve essere modificabile, ma non deve essere ridimensionabile. Questa implementazione scarica l'elenco specificato in un array, ordina l'array e scorre l'elenco ripristinando ciascun elemento dalla posizione corrispondente nell'array. Ciò evita le prestazioni di n2 log (n) che risulterebbero dal tentativo di ordinare un elenco collegato sul posto.

Il tipo di unione è probabilmente migliore della maggior parte dell'algoritmo di ricerca che puoi fare.

L'ho fatto nel modo seguente. il numero e il nome sono due arraylist. Devo ordinare il nome. Se si verifica una modifica al nome dell'ordine degli arralisti, anche l'arraylist cambia il suo ordine.

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);


                        }
                    }
                }
            }



}

usa questo metodo:

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 usa: mySortedlist = sortList(myList); Non è necessario implementare un comparatore nella tua classe. Se si desidera scambiare l'ordine inverso 1 e -1

È necessario utilizzare la funzione Arrays.sort. Le classi contenenti dovrebbero implementare Comparable.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top