按属性sorting自定义对象的ArrayList
我读了关于使用比较器对ArrayLists进行sorting,但是在所有的例子中,人们使用了compareTo
,根据一些研究,这是一个Strings的方法。
我想通过其属性之一来sorting自定义对象的ArrayList:Date对象( getStartDay()
)。 通常我通过item1.getStartDate().before(item2.getStartDate())
比较他们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); ... }
由于Date
实现了Comparable
,所以它有一个像String
一样的compareTo
方法。
所以你的自定义Comparator
可能是这样的:
public class CustomComparator implements Comparator<MyObject> { @Override public int compare(MyObject o1, MyObject o2) { return o1.getStartDate().compareTo(o2.getStartDate()); } }
compare()
方法必须返回一个int
,所以你不能直接返回一个boolean
就像你计划的那样。
你的sorting代码就像你写的:
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
您现在可以使用Comparator
器的lambdaexpression式以较短的forms编写最后一个示例:
Collections.sort(Database.arrayList, (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
List
有一个sort(Comparator)
方法,所以你可以进一步缩短:
Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
这是一个常见的习惯用法,有一个内置的方法可以用一个Comparable
键为一个类生成一个Comparator
:
Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));
所有这些都是等同的forms。
具有自然sorting顺序的类(例如类Number)应该实现Comparable接口,而没有自然sorting顺序的类(例如,Chair类)应该提供一个比较器(或一个匿名比较器类)。
两个例子:
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) { ... } });
为了sorting一个ArrayList
你可以使用下面的代码片断:
Collections.sort(studList, new Comparator<Student>(){ public int compare(Student s1, Student s2) { return s1.getFirstName().compareToIgnoreCase(s2.getFirstName()); } });
是的你可以。 比较项目有两个选项,比较接口和比较器接口。
这两个接口都允许不同的行为。 Comparable允许你使对象的行为像刚才描述的Strings(实际上,String implements Comparable)。 第二个比较器允许你做你要做的事情。 你会这样做:
Collections.sort(myArrayList, new MyComparator());
这将导致Collections.sort方法使用您的比较器的sorting机制。 如果ArrayList中的对象实现相似性,则可以改为执行下面的操作:
Collections.sort(myArrayList);
Collections类包含了许多这些有用的常用工具。
JAVA 8 lambdaexpression式
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)
在Java 8中,您可以使用比较器的方法引用:
import static java.util.Comparator.comparing; Collections.sort(list, comparing(MyObject::getStartDate));
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()); } } }
由于技术每天都会出现,所以答案会随时间而改变。 我看了一下LambdaJ,看起来很有趣。
你可以尝试用LambdaJ来解决这些任务。 你可以在这里find它: http : //code.google.com/p/lambdaj/
这里有一个例子:
sorting迭代
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()); } });
用lambdasorting
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
当然,这样的美performance会对性能产生影响(平均2次),但是你能find更易读的代码吗?
您可以使用Bean比较器对自定义类中的任何属性进行sorting。
从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 。
使用JAVA 8最简单的方法是英文字母sorting
课程实施
public class NewspaperClass implements Comparable<NewspaperClass>{ public String name; @Override public int compareTo(NewspaperClass another) { return name.compareTo(another.name); } }
分类
Collections.sort(Your List);
如果你想sorting包含非英文字母的字母,你可以使用语言环境…下面的代码使用土耳其字符sorting…
课程实施
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());
你可以尝试番石榴订购 :
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);
是的,这是可能的,例如在这个答案我sorting的属性v
的类IndexValue
// Sorting by property v using a custom comparator. Arrays.sort( array, new Comparator<IndexValue>(){ public int compare( IndexValue a, IndexValue b ){ return av - bv; } });
如果你在这里注意到我创build了一个匿名的内部类 (这是闭包的Java),并直接传递给类Arrays
的sort
方法
你的对象也可以实现Comparable
(这就是Java中的String和大多数核心库),但是它会自己定义类的“自然sorting顺序”,并且不允许你插入新的类。
这个代码片段可能是有用的。 如果你想在我的情况sorting一个对象,我想通过VolumeNamesorting:
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中使用它。
Java 8 Lambda缩短了sorting。
Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));
你可以使用java 8进行sorting
yourList.sort(Comparator.comparing(Classname::getName)); or yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));
我发现,如果不是所有这些答案都依赖于底层类(Object)来实现可比较的或者有一个帮助器可比的接口,
不是用我的解决scheme! 下面的代码让你通过知道它们的string名来比较对象的字段。 你可以很容易的修改它,而不是使用这个名字,但是你需要暴露它,或者构build一个你想比较的对象。
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); } } } }
有了这个库,您可以在多列上对自定义对象列表进行sorting。 该库使用8.0版function。 样品也可在那里。 这是一个样本
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);
2016年,您可以在德国斯图加特Java论坛看看这个演讲 。
只有less数幻灯片使用德语,99%的内容是“基于英语”的Java源代码; 喜欢
someCollection.sort( OurCustomComparator .comparing(Person::getName) .thenComparing(Person::getId) );
OurCustomComparator
使用默认的方法(和其他有趣的想法)。 如图所示,导致非常简洁的代码挑选一些getter方法进行sorting; 和超级简单的链接(或反转)的sorting标准。
如果你在java8中,你会发现很多的材料让你开始。
对于Java 8:
Collections.sort(list, comparing(ClassName::getName));
要么
Collections.sort(list, comparing(ClassName::getName).reversed());
它似乎与stringdatetypes也像“2015-12-14T21:55:51Z”
另一种方法是
Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));
您的customComparator类必须实现java.util.Comparator才能使用。 它也必须覆盖compare()和equals()
compare()必须回答以下问题:对象1是否小于,等于或大于对象2?
完整文档: http : //java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html
我更喜欢这个过程:
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
实现。
是的,这可能会更快…但是现在你不必为每种types都做一个新的比较器。 如果你可以节省开发时间并放弃运行时间,你可以使用这个。
自1.8以来新增了一个List.sort()方法,而不是使用Collection.sort(),因此您可以直接调用mylistcontainer.sort()
这是一个演示List.sort()function的代码片段:
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]
水果类是:
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类