按属性对自定义对象的ArrayList进行排序

1282

我了解到可以使用Comparator对ArrayList进行排序,但在所有示例中,人们都使用了compareTo方法,这是一种针对字符串的方法。

我想要通过一个自定义对象属性(Date类型的getStartDay()方法)来对ArrayList进行排序。通常,我会使用item1.getStartDate().before(item2.getStartDate()) 进行比较,所以我在想,是否可以编写类似以下方式的代码:

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

4
相关链接:https://dev59.com/NXI-5IYBdhLWcg3whYsr - BalusC
2
此帖中@Yishai的回答展示了枚举在自定义排序和分组排序(多个参数)中的优雅使用,利用比较器链接。 - gunalmel
29个回答

7

你可以使用Java 8来进行排序

yourList.sort(Comparator.comparing(Classname::getName));

or

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

6

6

Java 8 Lambda可以缩短排序时间。

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

2
Collections.sort(stdList, Comparator.comparing(SomeClass::getName)); - bcsb1001

5
我发现大多数答案都依赖于基础类(Object)实现comparable或具有helper comparable接口。
但我的解决方案不需要!以下代码允许您通过知道字段的字符串名称来比较对象。您可以很容易地修改它而不使用名称,但是那样您需要公开它或构造要与之比较的对象之一。
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);
            }
        }
    }
}

5

是的,例如在这个答案中,我按照类IndexValue的属性v进行排序。

    // Sorting by property v using a custom comparator.
    Arrays.sort( array, new Comparator<IndexValue>(){
        public int compare( IndexValue a, IndexValue b ){
            return a.v - b.v;
        }
    });

如果你注意这里,我正在创建一个匿名内部类(这是Java用于闭包的方式),并直接将其传递给类Arrays的sort方法。
你的对象也可以实现Comparable接口(这就是String和大多数Java核心库所做的),但这会定义类本身的“自然排序顺序”,而不允许你插入新的排序方式。

1
...但你可以使用Comparator来覆盖它 :) - BalusC

5

您可以尝试使用GuavaOrdering

Function<Item, Date> getStartDate = new Function<Item, Date>() {
    public Date apply(Item item) {
        return item.getStartDate();
    }
};

List<Item> orderedItems = Ordering.natural().onResultOf(getStartDate).
                          sortedCopy(items);

5
您可以使用“Bean Comparator”对自定义类中的任何属性进行排序。 点击此处了解更多信息。

5

如果你在使用Java 8或更早版本,这里提供了最佳解决方案。

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

在这种情况下,它将首先按照“getCgpa”的顺序进行排序,对于第二部分,它将根据pojo类中的“getFname”和“getId”字段进行排序。


1
这是Java 8或更新版本,不是Java8或更旧版本。 - d00d

3

自1.8版本开始,List.sort()方法取代了Collection.sort(),因此你可以直接调用mylistcontainer.sort()。

下面是一个演示List.sort()特性的代码片段:

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]

Fruit类是:

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   

3

使用这个库,您可以在多列上对自定义对象列表进行排序。该库使用8.0版本的功能。示例也可在此处找到。这是一个示例:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接