Sorteer ArrayLijst van aangepaste objecten op eigenschap

Ik heb gelezen over het sorteren van ArrayLists met behulp van een Comparator, maar in alle voorbeelden gebruikten mensen compareTo, wat volgens sommige onderzoeken een methode is voor Strings.

Ik wilde een ArrayList met aangepaste objecten sorteren op een van hun eigenschappen: een Date-object
(getStartDay()). Normaal gesproken vergelijk ik ze met item1.getStartDate().before(item2.getStartDate())dus ik vroeg me af of ik zoiets zou kunnen schrijven als:

public class CustomComparator {
    public boolean compare(Object object1, Object object2) {
        return object1.getStartDate().before(object2.getStartDate());
    }
}
public class RandomName {
    ...
    Collections.sort(Database.arrayList, new CustomComparator);
    ...
}

Antwoord 1, autoriteit 100%

Sinds Dateimplementeert Comparable, het heeft een compareTo-methode, net zoals Stringdat doet.

Dus uw aangepaste Comparatorzou er zo uit kunnen zien:

public class CustomComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
}

De compare()methode moet een intteruggeven, dus je kon niet direct een booleanteruggeven zoals je toch van plan was.

Uw sorteercode zou ongeveer zijn zoals u schreef:

Collections.sort(Database.arrayList, new CustomComparator());

Een iets kortere manier om dit alles te schrijven, als u uw comparator niet opnieuw hoeft te gebruiken, is door het te schrijven als een inline anonieme klasse:

Collections.sort(Database.arrayList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
});

Sinds java-8

Je kunt het laatste voorbeeld nu in een kortere vorm schrijven door een lambda-expressie te gebruiken voor de Comparator:

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

En Listheeft een sort(Comparator)methode, dus je kunt dit nog verder inkorten:

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

Dit is zo’n algemeen idioom dat er een ingebouwde methodeom een Comparatorte genereren voor een klasse met een Comparable-sleutel:

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));

Al deze zijn equivalente vormen.


2, Autoriteit 12%

Klassen met een natuurlijke sorteervolgorde (een klassenummer, als voorbeeld), moeten de vergelijkbare interface implementeren, terwijl klassen die geen natuurlijke sorteervolgorde hebben (een klasseverzoers, als voorbeeld), moet worden voorzien van een comparator (of een anonieme comparatorklasse).

Twee voorbeelden:

public class Number implements Comparable<Number> {
    private int value;
    public Number(int value) { this.value = value; }
    public int compareTo(Number anotherInstance) {
        return this.value - anotherInstance.value;
    }
}
public class Chair {
    private int weight;
    private int height;
    public Chair(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }
    /* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getWeight() - chair2.getWeight();
    }
}
class ChairHeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getHeight() - chair2.getHeight();
    }
}

Gebruik:

List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);
List<Chair> chairs = new ArrayList<Chair>();
// Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
// Sort by height:
Collections.sort(chairs, new ChairHeightComparator());
// You can also create anonymous comparators;
// Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
    public int compare(Chair chair1, Chair chair2) {
        ...
    }
});

3, Autoriteit 10%

Voor het sorteren van een ArrayListU kunt het volgende codefragment gebruiken:

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});

4, Autoriteit 3%

Ja, dat kan. Er zijn twee opties met het vergelijken van items, de vergelijkbaar Interface en de comparator interface.

Beide interfaces maken een ander gedrag mogelijk. Vergelijkbaar stelt u in staat om het object te laten werken zoals u zojuist reeksen hebt beschreven (in feite, stringimplementeert vergelijkbaar). Met de tweede, comparator, kunt u doen wat u vraagt ​​om te doen. Je zou het zo doen:

Collections.sort(myArrayList, new MyComparator());

Dat zorgt ervoor dat de methode van de verzameling.Sort uw comparator gebruikt voor het sorteermechanisme. Als de objecten in de Arraylijst vergelijkbaar zijn, kunt u in plaats daarvan zoiets doen:

Collections.sort(myArrayList);

De Collecties Klasse bevat een nummer van deze nuttige, gemeenschappelijke hulpmiddelen.


5, Autoriteit 3%

JAVA 8 LAMBDA-expressie

Collections.sort(studList, (Student s1, Student s2) ->{
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});

of

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)

6, Autoriteit 2%

Met Java 8 kunt u een methode-referentie voor uw comparator gebruiken:

import static java.util.Comparator.comparing;
Collections.sort(list, comparing(MyObject::getStartDate));

7

Omdat technologieën elke dag verschijnen, zal het antwoord in de tijd veranderen. Ik nam een ​​kijkje op Lambdaj en lijkt erg interessant.

U kunt proberen deze taken op te lossen met lambdaj . Je kunt het hier vinden: http://code.google.com/p/lambdaj/

Hier hebt u een voorbeeld:

sorteer iteratief

List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
});

Sorteren met Lambda

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

Natuurlijk, met dit soort schoonheidseffecten in de uitvoering (gemiddeld 2 keer), maar kunt u een meer leesbare code vinden?


8

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
public class test {
public static class Person {
    public String name;
    public int id;
    public Date hireDate;
    public Person(String iname, int iid, Date ihireDate) {
        name = iname;
        id = iid;
        hireDate = ihireDate;
    }
    public String toString() {
        return name + " " + id + " " + hireDate.toString();
    }
    // Comparator
    public static class CompId implements Comparator<Person> {
        @Override
        public int compare(Person arg0, Person arg1) {
            return arg0.id - arg1.id;
        }
    }
    public static class CompDate implements Comparator<Person> {
        private int mod = 1;
        public CompDate(boolean desc) {
            if (desc) mod =-1;
        }
        @Override
        public int compare(Person arg0, Person arg1) {
            return mod*arg0.hireDate.compareTo(arg1.hireDate);
        }
    }
}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    SimpleDateFormat df = new SimpleDateFormat("mm-dd-yyyy");
    ArrayList<Person> people;
    people = new ArrayList<Person>();
    try {
        people.add(new Person("Joe", 92422, df.parse("12-12-2010")));
        people.add(new Person("Joef", 24122, df.parse("1-12-2010")));
        people.add(new Person("Joee", 24922, df.parse("12-2-2010")));
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    Collections.sort(people, new Person.CompId());
    System.out.println("BY ID");
    for (Person p : people) {
        System.out.println(p.toString());
    }
    Collections.sort(people, new Person.CompDate(false));
    System.out.println("BY Date asc");
    for (Person p : people) {
        System.out.println(p.toString());
    }
    Collections.sort(people, new Person.CompDate(true));
    System.out.println("BY Date desc");
    for (Person p : people) {
        System.out.println(p.toString());
    }
}
}

9

Beste eenvoudige manier met Java 8 is voor Engels alfabetisch sorteer

Class Implementation

public class NewspaperClass implements Comparable<NewspaperClass>{
   public String name;
   @Override
   public int compareTo(NewspaperClass another) {
      return name.compareTo(another.name);
   }
}

sorteren

 Collections.sort(Your List);

Als u wilt sorteren op alfabet dat niet-Engelse tekens bevat, kunt u Locale gebruiken … Onderstaande code Gebruik Turkish Character Sort …

Class Implementation

public class NewspaperClass implements Comparator<NewspaperClass> {
   public String name;
   public Boolean isUserNewspaper=false;
   private Collator trCollator = Collator.getInstance(new Locale("tr_TR"));
   @Override
   public int compare(NewspaperClass lhs, NewspaperClass rhs) {
      trCollator.setStrength(Collator.PRIMARY);
      return trCollator.compare(lhs.name,rhs.name);
   }
}

sorteren

Collections.sort(your array list,new NewspaperClass());

10

Functie & methode referentie

De Collections.sort-methode kan een Listmet een Comparatordie je hebt doorstaan . Die Comparatorkan worden geïmplementeerd met behulp van de Comparator.comparing-methode waarmee u een methodereferentieals de noodzakelijke Function. Gelukkig is de eigenlijke code veel eenvoudiger en korter dan deze beschrijving.

Voor Java 8:

Collections.sort(list, comparing(ClassName::getName));

of

Collections.sort(list, comparing(ClassName::getName).reversed());

Een andere manier is

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));

Antwoord 11

U kunt sorteren met java 8

yourList.sort(Comparator.comparing(Classname::getName));
or
yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));

Antwoord 12

Vanaf Java 8en verder hoeven we Collections.sort()niet rechtstreeks te gebruiken. Listinterface heeft een standaard sort()methode:

List<User> users = Arrays.asList(user1,user2,user3);
users.sort( (u1, u2) -> { 
return u1.getFirstName.compareTo(u2.getFirstName());}); 

Zie http://visvv.blogspot.in /2016/01/sorting-objects-in-java-8.html.


Antwoord 13

Java 8 Lambda verkort de sortering.

Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));

Antwoord 14

Je kunt de Bonenvergelijkergebruiken om op elke eigenschap te sorteren in je aangepaste klas.


15

Ik vond het meest, zo niet al deze antwoorden vertrouwen op de onderliggende klasse (object) om vergelijkbaar te implementeren of om een ​​helper vergelijkbare interface te hebben.

Niet met mijn oplossing! Met de volgende code kunt u het veld van het object vergelijken door hun stringnaam te kennen. U kunt het eenvoudig wijzigen om de naam niet te gebruiken, maar dan moet u deze blootstellen of een van de objecten die u wilt vergelijken met.

Collections.sort(anArrayListOfSomeObjectPerhapsUsersOrSomething, new ReflectiveComparator(). new ListComparator("name"));
public class ReflectiveComparator {
    public class FieldComparator implements Comparator<Object> {
        private String fieldName;
        public FieldComparator(String fieldName){
            this.fieldName = fieldName;
        }
        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Comparable object1FieldValue = (Comparable) field.get(object1);
                Comparable object2FieldValue = (Comparable) field.get(object2);
                return object1FieldValue.compareTo(object2FieldValue);
            }catch (Exception e){}
            return 0;
        }
    }
    public class ListComparator implements Comparator<Object> {
        private String fieldName;
        public ListComparator(String fieldName) {
            this.fieldName = fieldName;
        }
        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Comparable o1FieldValue = (Comparable) field.get(object1);
                Comparable o2FieldValue = (Comparable) field.get(object2);
                if (o1FieldValue == null){ return -1;}
                if (o2FieldValue == null){ return 1;}
                return o1FieldValue.compareTo(o2FieldValue);
            } catch (NoSuchFieldException e) {
                throw new IllegalStateException("Field doesn't exist", e);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Field inaccessible", e);
            }
        }
    }
}

Antwoord 16

uw customComparator-klasse moet java.util.Comparator implementeren om te kunnen worden gebruikt.
het moet ook overschrijven vergelijk() AND is gelijk aan()

compare() moet de vraag beantwoorden: Is object 1 kleiner dan, gelijk aan of groter dan object 2?

volledige documenten: http:// java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html


Antwoord 17

Deze codefragmenten kunnen nuttig zijn. Als u een object wilt sorteren
in mijn geval wil ik sorteren op VolumeName:

public List<Volume> getSortedVolumes() throws SystemException {
    List<Volume> volumes = VolumeLocalServiceUtil.getAllVolumes();
    Collections.sort(volumes, new Comparator<Volume>() {
        public int compare(Volume o1, Volume o2) {
            Volume p1 = (Volume) o1;
            Volume p2 = (Volume) o2;
            return p1.getVolumeName().compareToIgnoreCase(
                    p2.getVolumeName());
        }
    });
    return volumes;
}

Dit werkt. Ik gebruik het in mijn jsp.


Antwoord 18

Met deze bibliotheek hierkun je sorteer de lijst met aangepaste objecten op meerdere kolommen. De bibliotheek gebruikt functies van versie 8.0. Monster is daar ook beschikbaar. Hier is een voorbeeld om te doen

SortKeys sortKeys = new SortKeys();
sortKeys.addField("firstName")
            .addField("age", true); // This (true) will sort the age descending
// Other ways to specify a property to the sorter are
//      .addField("lastName", String.class);
//      .addField("dob", Date.class, true);
// Instantiate a ListSorter
ListSorter listSorter = new ListSorter();
// Pass the data to sort (listToSort) and the "by keys" to sort (sortKeys)
List sortedList = (List<Person>) listSorter.sortList(listToSort, sortKeys);

19

U kunt hier een kijk op deze presentatie houden op de Java Forum in Stuttgart Duitsland in 2016.

Slechts een paar dia’s gebruiken de Duitse taal, 99% van de inhoud is “Engelse opgelegde” Java-broncode; zoals

someCollection.sort(
  OurCustomComparator
    .comparing(Person::getName)
    .thenComparing(Person::getId)
);

Waar OurCustomComparatoris het gebruik van standaardmethoden (en andere interessante ideeën). Zoals getoond, leidt tot zeer beknopte code om wat getter-methode voor sortering te kiezen; en super eenvoudige chaining (of omkeren) van sorteercriteria.

Als u in Java8 bent, vindt u daar veel materiaal om u op weg te helpen.


20

Nieuw sinds 1.8 is een lijst.Sort () -methode in plaats van het gebruik van de collectie.Sort ()
Dus u belt rechtstreeks mylistcontainer.sort ()

Hier is een codefragment die de lijst aan de lijst () toont:

List<Fruit> fruits = new ArrayList<Fruit>();
fruits.add(new Fruit("Kiwi","green",40));
fruits.add(new Fruit("Banana","yellow",100));
fruits.add(new Fruit("Apple","mixed green,red",120));
fruits.add(new Fruit("Cherry","red",10));
// a) using an existing compareto() method
fruits.sort((Fruit f1,Fruit f2) -> f1.getFruitName().compareTo(f2.getFruitName()));
System.out.println("Using String.compareTo(): " + fruits);
//Using String.compareTo(): [Apple is: mixed green,red, Banana is: yellow, Cherry is: red, Kiwi is: green]
// b) Using a comparable class
fruits.sort((Fruit f1,Fruit f2) -> f1.compareTo(f2));  
System.out.println("Using a Comparable Fruit class (sort by color): " + fruits);
// Using a Comparable Fruit class (sort by color): [Kiwi is green, Apple is: mixed green,red, Cherry is: red, Banana is: yellow]

De Fruit-klasse is:

public class Fruit implements Comparable<Fruit>
{
    private String name;
    private String color;
    private int quantity;
    public Fruit(String name,String color,int quantity)
    { this.name = name; this.color = color; this.quantity = quantity; }
    public String getFruitName() { return name; }        
    public String getColor() { return color; }  
    public int getQuantity() { return quantity; }
    @Override public final int compareTo(Fruit f) // sorting the color
    {
        return this.color.compareTo(f.color);
    }     
    @Override public String toString()
    {   
        return (name + " is: " + color);
    }
} // end of Fruit class   

Antwoord 21

Ik geef de voorkeur aan dit proces:

public class SortUtil
{    
    public static <T> List<T> sort(List<T> list, String sortByProperty)
    {
            Collections.sort(list, new BeanComparator(sortByProperty));
            return list;
    }
}
List<T> sortedList = SortUtil<T>.sort(unsortedList, "startDate");

Als uw lijst met objecten een eigenschap heeft met de naam startDate, roept u use deze steeds opnieuw aan. Je kunt ze zelfs startDate.timekoppelen.

Hiervoor moet je object Comparablezijn, wat betekent dat je een compareTo, equalsen hashCode-implementatie nodig hebt .

Ja, het kan sneller… Maar nu hoef je niet voor elk type sortering een nieuwe Comparator te maken. Als je ontwikkeltijd kunt besparen en runtime kunt opgeven, kun je voor deze gaan.


Antwoord 22

Als je Java 8 of een oudere versie gebruikt, is dit de beste oplossing.

Collections.sort(studentList, Comparator.comparing(Student::getCgpa).reversed().thenComparing(Student:: getFname).thenComparing(Student::getId));

In dit geval sorteert het eerst met ‘getCgpa’ en voor het tweede deel met getFname en getId. Dat is veld in de pojo-klasse.


Antwoord 23

Gebruik van Java 8 kan de Comparatorin één regel definiëren met behulp van Comparator.comparing()

Gebruik een van de volgende manieren:

Optie 1:

listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));

Optie 2:

Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));

Antwoord 24

Uw aangepaste klasse kan de “Vergelijkbare” interface implementeren, waarvoor een implementatie van de CompareTo-methode vereist is. In de CompareTo-methode kunt u vervolgens definiëren wat het betekent dat een object kleiner of groter is danhet andere object. Dus in jouw voorbeeld kan het er ongeveer zo uitzien:

public class MyCustomClass implements Comparable<MyCustomClass>{

……….

@Override
public int compareTo(MyCustomClass a) {
    if(this.getStartDate().before(a.getStartDate())){
        return -1;
    }else if(a.getStartDate().before(this.getStartDate())){
        return 1;
    }else {
        return 0;
    }
}

Een negatief getal geeft aan dat ditkleiner is dan het object waarmee wordt vergeleken. Een positief getal geeft aan dat ditgroter is dan het vergeleken met object en een nul betekent dat de objecten gelijk zijn.

U kunt dan collections.sort(myList) gebruiken om uw lijst te sorteren zonder dat u een comparator hoeft in te voeren. Deze methode heeft ook het voordeel dat dingen automatisch worden gesorteerd als u een gesorteerde verzameling gegevensstructuren gebruikt, zoals een TreeSet of een TreeMap.

Je kunt dit artikel raadplegen als je meer wilt lezen over de vergelijkbare interface (openbaarmaking: ik ben de auteur 😉 )
https://nullbeans.com/the-java-comparable -interface-automatic-sort-of-collections/


Antwoord 25

Je zou ook Springs PropertyComparatorals je alleen een String-eigenschapspad hebt naar de (geneste) eigenschap die je wilt sorteren:

List<SomeObject> list = ...;
PropertyComparator<HitWithInfo> propertyComparator = new PropertyComparator<>(
    "property.nested.myProperty", false, true);
list.sort(propertyComparator);

Het nadeel is, dat deze comparator stilzwijgend eigenschappen negeert die niet bestaan of niet toegankelijk zijn en dit als nullwaarde voor vergelijking behandelt. Dit betekent dat u zo’n comparator zorgvuldig moet testen of het bestaan van het eigenschapspad op de een of andere manier moet valideren.


Antwoord 26

met behulp van de java-8 stream-api kunt u een ArrayListsorteren op:

Comparator<Person> birthdayComparator = Comparator.comparing(Person::getBirthday);
 List<Person> sortedList = list.stream().sorted(birthdayComparator).collect(toList());

Antwoord 27

Ik heb veel verschillende oplossingen geprobeerd die beschikbaar zijn op internet, maar een oplossing die voor mij werkt, is beschikbaar via onderstaande link.

https://www .java67.com/2017/07/how-to-sort-arraylist-of-objects-using.html

Other episodes