首页 文章

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

提问于
浏览
1000

我读到了使用比较器对ArrayLists进行排序,但在所有示例中,人们使用 compareTo ,根据一些研究,这是一个字符串的方法 .

我想通过它们的一个属性对自定义对象的ArrayList进行排序:Date对象( getStartDay() ) . 通常我会用 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);
    ...
}

24 回答

  • 3

    此代码段可能很有用 . 如果你想在我的情况下对Object进行排序,我想按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;
    }
    

    这很有效 . 我在我的jsp中使用它 .

  • 2

    You can Sort using java 8

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

    我更喜欢这个过程:

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

    如果对象列表中有一个名为 startDate 的属性,则可以反复使用此属性 . 你甚至可以链接他们 startDate.time .

    这需要您的对象为 Comparable ,这意味着您需要 compareToequalshashCode 实现 .

    是的,它可能会更快......但是现在你不必为每种类型的排序制作新的比较器 . 如果你可以节省开发时间并放弃运行时,你可以选择这个 .

  • 14

    您可以使用Bean Comparator对自定义类中的任何属性进行排序 .

  • 4

    使用Java 8,您可以使用比较器的方法引用:

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

    具有自然排序顺序的类(作为示例的类Number)应该实现Comparable接口,而没有自然排序顺序的类(作为示例的类)应该与比较器(或匿名比较器)一起提供类) .

    两个例子:

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

    用法:

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

    您的customComparator类必须实现java.util.Comparator才能使用 . 它还必须覆盖compare()AND equals()

    compare()必须回答这个问题:对象1是否小于,等于或大于对象2?

    完整文档:http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html

  • 5

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

    } // Fruit类的结尾

  • 41

    使用此库here,您可以对多列上的自定义对象列表进行排序 . 该库使用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);
    
  • 0

    由于技术每天都会出现,答案会随着时间的推移而改变 . 我看了看LambdaJ,看起来非常有趣 .

    您可以尝试使用 LambdaJ 解决这些任务 . 你可以在这里找到它:http://code.google.com/p/lambdaj/

    这里有一个例子:

    Sort Iterative

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

    Sort with lambda

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

    当然,拥有这种美感会影响性能(平均2次),但是你能找到更易读的代码吗?

  • 3

    JAVA 8 lambda表达式

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

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

    对于Java 8:

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

    要么

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

    另一种方式是

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

    是的你可以 . 比较项目有两个选项,Comparable接口和Comparator接口 .

    这两种接口都允许不同的行为 . Comparable允许您使对象的行为与刚才描述的字符串一样(实际上,String实现了Comparable) . 第二个,比较器,允许你做你要做的事情 . 你会这样做:

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

    这将导致Collections.sort方法将比较器用于它的排序机制 . 如果ArrayList中的对象具有可比性,则可以执行以下操作:

    Collections.sort(myArrayList);
    

    Collections类包含许多这些有用的常用工具 .

  • 1

    Java 8 开始,我们不必直接使用 Collections.sort() . List 接口有一个默认的 sort() 方法:

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

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

  • 9

    是的,例如在this answer中我可以按类 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)并将其直接传递给类 Arrayssort 方法

    您的对象也可以实现 Comparable ('s what String and most of the core libraries in Java does ) but that would define the 427876 of the class it self, and doesn' t让您插入新的 .

  • 3

    使用Java 8,可以使用 Comparator.comparing() 在一行中定义 Comparator

    使用以下任何一种方式:

    Option 1:

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

    Option 2:

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

    要对 ArrayList 进行排序,您可以使用以下代码段:

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

    使用JAVA 8的最简单方法是英语字母排序

    Class Implementation

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

    Sort

    Collections.sort(Your List);
    

    如果要对包含非英文字符的字母进行排序,可以使用Locale ...下面的代码使用土耳其字符排序...

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

    Sort

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

    你可以试试Guava Ordering

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

    您可以在2016年德国斯图加特的Java论坛上了解这个presentation .

    只有少数幻灯片使用德语,99%的内容是“基于英语”的Java源代码;喜欢

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

    其中 OurCustomComparator 正在使用默认方法(和其他有趣的想法) . 如图所示,导致非常简洁的代码来选择一些getter方法进行排序;和排序标准的超级简单链接(或逆转) .

    如果您使用的是java8,那么您可以找到很多材料来帮助您入门 .

  • 188

    Java 8 Lambda缩短了排序 .

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

    由于Date实现Comparable,它有一个 compareTo 方法,就像 String 一样 .

    所以你的自定义Comparator可能如下所示:

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

    compare() 方法必须返回 int ,因此您无法直接返回 boolean ,就像您计划的那样 .

    你的排序代码就像你写的那样:

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

    如果你不需要重用你的比较器,那么编写所有这些的稍微简短的方法就是将它写成内联匿名类:

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

    自java-8以来

    您现在可以使用lambda expressionComparator 以较短的形式编写最后一个示例:

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

    List 有一个sort(Comparator)方法,所以你可以进一步缩短它:

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

    这是一个常见的习惯用法,a built-in method为一个带有 Comparable 键的类生成 Comparator

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

    所有这些都是等效的形式 .

  • 1
    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());
        }
    
    }
    
    }
    
  • 27

    我发现大多数(如果不是全部)这些答案都依赖于底层类(Object)来实现可比较的或具有可比较的辅助接口 .

    不是我的解决方案!以下代码允许您通过了解其字符串名称来比较对象的字段 . 您可以轻松地修改它而不使用名称,但是您需要公开它或构造一个您想要比较的对象 .

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

相关问题