我读到了使用比较器对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);
...
}
答案 0 :(得分:1435)
自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());
}
});
现在,您可以使用Comparator
的{{3}}以较短的格式编写最后一个示例:
Collections.sort(Database.arrayList,
(o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
List
有一个lambda expression方法,因此您可以进一步缩短这一点:
Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
这是一个常见的习惯用法,sort(Comparator)
为Comparator
密钥的类生成Comparable
:
Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));
所有这些都是等效形式。
答案 1 :(得分:190)
具有自然排序顺序的类(作为示例的类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) {
...
}
});
答案 2 :(得分:153)
要对ArrayList
进行排序,您可以使用以下代码段:
Collections.sort(studList, new Comparator<Student>(){
public int compare(Student s1, Student s2) {
return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
}
});
答案 3 :(得分:42)
是的,你可以。比较项目有两个选项,Comparable界面和Comparator界面。
这两种接口都允许不同的行为。 Comparable允许您使对象的行为与您刚刚描述的Strings一样(事实上,String实现了Comparable)。第二个,比较器,允许你做你想要做的事情。你会这样做:
Collections.sort(myArrayList, new MyComparator());
这会导致Collections.sort方法将比较器用于它的排序机制。如果ArrayList中的对象具有可比性,则可以执行以下操作:
Collections.sort(myArrayList);
Collections类包含许多这些有用的常用工具。
答案 4 :(得分:36)
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)
答案 5 :(得分:30)
使用Java 8,您可以使用比较器的方法参考:
import static java.util.Comparator.comparing;
Collections.sort(list, comparing(MyObject::getStartDate));
答案 6 :(得分: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());
}
});
以lambda排序
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
当然,拥有这种美感会影响性能(平均2次),但你能找到更易读的代码吗?
答案 7 :(得分: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());
}
}
}
答案 8 :(得分:9)
JAVA 8的最简单方法是英语字母排序
班级实施
public class NewspaperClass implements Comparable<NewspaperClass>{
public String name;
@Override
public int compareTo(NewspaperClass another) {
return name.compareTo(another.name);
}
}
<强>排序强>
Collections.sort(Your List);
如果要对包含非英文字符的字母进行排序,可以使用区域设置...以下代码使用土耳其字符排序...
班级实施
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);
}
}
<强>排序强>
Collections.sort(your array list,new NewspaperClass());
答案 9 :(得分:7)
Collections.sort
方法可以使用您传递的List
对Comparator
进行排序。可以使用Comparator.comparing
方法实施Comparator
,您可以将method reference作为必要Function
传递。幸运的是,实际代码比此描述更简单,更短。
对于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())));
答案 10 :(得分:6)
从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。
答案 11 :(得分:5)
是的,例如在this answer中我可以按类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;
}
});
如果你注意到这里我正在创建一个匿名内部类(它是闭包的Java)并将它直接传递给类sort
的{{1}}方法
您的对象也可能实现Arrays
(这就是String和Java中的大多数核心库所做的那样)但是这将定义它自己的类的“自然排序顺序”,并且不会让您插入新的。
答案 12 :(得分:5)
您可以使用Bean Comparator对自定义类中的任何属性进行排序。
答案 13 :(得分:5)
您可以尝试番石榴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);
答案 14 :(得分:5)
Java 8 Lambda缩短了排序。
Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));
答案 15 :(得分:5)
您可以使用java 8进行排序
yourList.sort(Comparator.comparing(Classname::getName));
or
yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));
答案 16 :(得分:4)
我发现大多数(如果不是所有这些答案都依赖于底层类(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);
}
}
}
}
答案 17 :(得分:3)
此代码段可能很有用。如果要对对象进行排序 在我的情况下,我想按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中使用它。
答案 18 :(得分:3)
您可以在2016年德国斯图加特的Java论坛上查看此presentation暂存。
只有少数幻灯片使用德语,99%的内容是“基于英语”的Java源代码;像
someCollection.sort(
OurCustomComparator
.comparing(Person::getName)
.thenComparing(Person::getId)
);
其中OurCustomComparator
使用默认方法(和其他有趣的想法)。如图所示,导致非常简洁的代码选择一些getter方法进行排序;和超级简单的链接(或反转)排序标准。
如果您使用的是java8,那么您可以找到很多材料来帮助您入门。
答案 19 :(得分:2)
新的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
答案 20 :(得分:2)
使用此库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);
答案 21 :(得分:2)
您的customComparator类必须实现java.util.Comparator才能使用。 它还必须覆盖compare()AND equals()
compare()必须回答这个问题:对象1是否小于,等于或大于对象2?
完整文档:http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html
答案 22 :(得分:1)
我更喜欢这个过程:
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
,这意味着您需要compareTo
,equals
和hashCode
实施。
是的,它可能会更快......但是现在你不必为每种类型的排序制作一个新的Comparator。如果你可以节省开发时间并放弃运行时,你可以选择这个。
答案 23 :(得分:0)
使用Java 8,可以使用Comparator
Comparator.comparing()
使用以下任何一种方式:
选项1:
listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));
选项2:
Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));
答案 24 :(得分:0)
您的自定义类可以实现“ Comparable”接口,该接口需要执行CompareTo方法。然后,在CompareTo方法中,可以定义一个对象小于或小于另一个对象的含义。因此,在您的示例中,它看起来可能像这样:
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;
}
}
负数表示此小于要比较的对象。正数表示此大于与对象的比较值,零则表示对象相等。
然后,您可以使用collections.sort(myList)对列表进行排序,而无需提供比较器。如果使用诸如TreeSet或TreeMap之类的排序集合数据结构,此方法还具有使事物自动排序的优点。
如果您想阅读有关Comparable接口的更多信息,可以查看本文(披露:我是作者;)) https://nullbeans.com/the-java-comparable-interface-automatic-sort-of-collections/
答案 25 :(得分:0)
如果您仅具有要排序的(嵌套)属性的String属性路径,则也可以使用Springs PropertyComparator:
List<SomeObject> list = ...;
PropertyComparator<HitWithInfo> propertyComparator = new PropertyComparator<>(
"property.nested.myProperty", false, true);
list.sort(propertyComparator);
缺点是,该比较器会默默地忽略不存在或不可访问的属性,并将其作为 null 值进行比较。这意味着,您应该仔细测试这样的比较器或以某种方式验证属性路径的存在。
答案 26 :(得分:0)
使用java-8流api可以对ArrayList
进行排序:
Comparator<Person> birthdayComparator = Comparator.comparing(Person::getBirthday);
List<Person> sortedList = list.stream().sorted(birthdayComparator).collect(toList());
答案 27 :(得分:0)
我尝试了Internet上提供的许多不同解决方案,但是可以在下面的链接中找到适合我的解决方案。
https://www.java67.com/2017/07/how-to-sort-arraylist-of-objects-using.html
答案 28 :(得分:0)
好吧,如果您使用Java 8或更早版本,这是最好的解决方案。
Collections.sort(studentList, Comparator.comparing(Student::getCgpa).reversed().thenComparing(Student:: getFname).thenComparing(Student::getId));
在这种情况下,它将首先使用'getCgpa'进行排序,第二部分将使用getFname和getId进行排序。这是pojo类的一个领域。