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

Sam*_*uel 1093 java sorting date comparator

我读到了使用Comparator对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);
    ...
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*ers 1483

自从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());
    }
}
Run Code Online (Sandbox Code Playgroud)

compare()方法必须返回一个int,所以你无法直接返回boolean你计划的那样.

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

Collections.sort(Database.arrayList, new CustomComparator());
Run Code Online (Sandbox Code Playgroud)

如果你不需要重用你的比较器,写一个稍微短一点的方法是将它写成内联匿名类:

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

您现在可以使用lambda表达式以更短的形式编写最后一个示例Comparator:

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
Run Code Online (Sandbox Code Playgroud)

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

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
Run Code Online (Sandbox Code Playgroud)

这是一个常见的习惯用法,有一个内置的方法来生成一个Comparator带有Comparable键的类:

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));
Run Code Online (Sandbox Code Playgroud)

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

  • 提到它应该返回`int`并且你最好使用`Date#compareTo()`来+1.为什么这个没有在其他答案之上被投票超出我的范围.此链接也可能有用:[Sun.com上的对象订购教程](http://java.sun.com/docs/books/tutorial/collections/interfaces/order.html). (32认同)
  • 我认为最好的答案还应该包括在Java 8中实现它的正确方法.Collections.sort(list,Comparator.comparing(MyObject :: getStartDate)); 哪个读取更好,更不容易出错.写返回o1.getStartDate().compareTo(o1.getStartDate()); (5认同)
  • @Kuba更好,使用`List.sort()`. (3认同)
  • 此解决方案不适用于Android API <24.你们知道解决方案吗? (3认同)
  • 比较类应该是静态的:) (2认同)
  • 使用`s1.compareTo(s2)`时字符串排序的顺序默认为asc,使用`s2.compareTo(s1)`时默认为desc (2认同)
  • 如果您使用的是 Java 8,请看看是否可以摆脱“Date”,转而使用“java.time”包中新的、对程序员更友好的类之一。 (2认同)

Bjö*_*örn 192

具有自然的排列顺序(一类号码,作为一个例子)类应该实现Comparable接口,同时不具有天然的排序顺序(A类主席,作为一个例子)班应提供一个比较器(或匿名的比较类).

两个例子:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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) {
        ...
    }
});
Run Code Online (Sandbox Code Playgroud)


小智 156

对于排序,ArrayList您可以使用以下代码段:

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


ape*_*ins 43

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

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

Collections.sort(myArrayList, new MyComparator());
Run Code Online (Sandbox Code Playgroud)

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

Collections.sort(myArrayList);
Run Code Online (Sandbox Code Playgroud)

集合类包含了一些这些有用的,常用工具.


Sor*_*ter 40

JAVA 8 lambda表达式

Collections.sort(studList, (Student s1, Student s2) ->{
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});
Run Code Online (Sandbox Code Playgroud)

要么

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)
Run Code Online (Sandbox Code Playgroud)

  • ..或`studList.sort(Comparator.comparing(Student :: getFirstName));` (5认同)
  • 或者`Collections.sort(studList,Comparator.comparing(Student :: getFirstName));` (3认同)

ass*_*ias 31

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

import static java.util.Comparator.comparing;

Collections.sort(list, comparing(MyObject::getStartDate));
Run Code Online (Sandbox Code Playgroud)


Fed*_*zza 14

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

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

这里有一个例子:

排序迭代

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());
        }
});
Run Code Online (Sandbox Code Playgroud)

用lambda排序

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 
Run Code Online (Sandbox Code Playgroud)

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


Cha*_*esW 13

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

}

}
Run Code Online (Sandbox Code Playgroud)

  • 欢迎来到stackoverflow.这个问题前一段时间得到了回答.在恢复旧线程之前,请确保您的响应为线程添加了一些重要内容. (7认同)
  • 请在您的答案中添加解释。 (2认同)

Bey*_*yaz 9

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

课程实施

public class NewspaperClass implements Comparable<NewspaperClass>{
   public String name;

   @Override
   public int compareTo(NewspaperClass another) {
      return name.compareTo(another.name);
   }
}
Run Code Online (Sandbox Code Playgroud)

分类

  Collections.sort(Your List);
Run Code Online (Sandbox Code Playgroud)

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

课程实施

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

分类

Collections.sort(your array list,new NewspaperClass());
Run Code Online (Sandbox Code Playgroud)


Aru*_*run 8

功能和方法参考

Collections.sort方法可以List使用Comparator您传递的方式对其进行排序.这Comparator可以使用Comparator.comparing您可以根据需要传递方法引用的方法来实现Function.幸运的是,实际代码比这个描述简单得多,也更短.

对于Java 8:

Collections.sort(list, comparing(ClassName::getName));
Run Code Online (Sandbox Code Playgroud)

要么

Collections.sort(list, comparing(ClassName::getName).reversed());
Run Code Online (Sandbox Code Playgroud)

另一种方式是

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));
Run Code Online (Sandbox Code Playgroud)


Vis*_*van 6

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

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

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


cam*_*ckr 5

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


Osc*_*Ryz 5

是的,例如在这个答案中我可以按v类的属性排序IndexValue

    // 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;
        }
    });
Run Code Online (Sandbox Code Playgroud)

如果你在这里注意到我正在创建一个匿名内部类(它是用于闭包的Java)并将其直接传递给sort类的方法Arrays

你的对象也可以实现Comparable(这就是String和Java中的大多数核心库所做的那样)但是它会定义它自己的类的"自然排序顺序",并且不会让你插入新的.


Kev*_*ker 5

我发现大多数(如果不是全部)这些答案都依赖于底层类 (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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Vit*_*nko 5

您可以尝试番石榴订购:

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);
Run Code Online (Sandbox Code Playgroud)


jav*_*ior 5

Java 8 Lambda缩短了排序.

Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));
Run Code Online (Sandbox Code Playgroud)

  • `Collections.sort(stdList, Comparator.comparing(SomeClass::getName));` (2认同)

See*_*ker 5

您可以使用java 8进行排序

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

or

yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));
Run Code Online (Sandbox Code Playgroud)


Kri*_*hna 5

如果您使用 Java 8 或更旧版本,这是最好的解决方案。

Collections.sort(studentList, Comparator.comparing(Student::getCgpa).reversed().thenComparing(Student:: getFname).thenComparing(Student::getId));
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它将首先使用“getCgpa”进行排序,第二部分将使用 getFname 和 getId 进行排序。这是 pojo 类中的字段。