按日期排序对象列表 属性
Sorting list of objects by date property
我有一个包含两个 LocalDate 属性的对象:
public class SomeObject {
private LocalDate startDate;
private LocalDate endDate;
}
为简洁起见省略了构造函数和内容。我想按开始日期对这些对象的列表进行排序,然后将下一个对象的开始日期分配给前一个对象的结束日期。为了澄清,我从这些对象的列表开始:
SomeObject object1 = new SomeObject(LocalDate.parse("2015-01-01"), null);
SomeObject object2 = new SomeObject(LocalDate.parse("2014-01-01"), null);
SomeObject object3 = new SomeObject(LocalDate.parse("2016-01-01"), null);
List<SomeObject> list = Arrays.asList(object1, object2, object3);
排序后应该return这样:
for (SomeObject object : list) {
System.out.println(object.startDate.toString() + " " + object.endDate.toString() );
}
2014-01-01 2015-01-01
2015-01-01 2016-01-01
2016-01-01 null
每个列表最多只包含 3 或 4 个这样的对象,但代码可能必须处理数万个这样的列表,因此我正在寻找一种有效的方法来执行此操作。
您可以将 Collections.sort 与比较器一起使用。在使用 Lambdas 的 Java 8 中,它看起来像这样:
Collections.sort(list, (x, y) -> x.startDate.compareTo(y.startDate));
for (int i = 0; i < (list.size() - 1); i++) {
list.get(i).endDate = list.get(i + 1).startDate;
}
利用 LocalDate
已经 implements Comparable
这一事实,让你的 SomeObject
也这样做。此外,给它一个适当的 toString()
方法,它处理 null
值,以便将您的对象表示为 String
:
public class SomeObject implements Comparable<SomeObject> {
private LocalDate startDate;
private LocalDate endDate;
public SomeObject(LocalDate startDate, LocalDate endDate) {
this.startDate = startDate;
this.endDate = endDate;
}
@Override
public int compareTo(SomeObject anotherObject) {
return this.startDate.compareTo(anotherObject.startDate);
}
@Override
public String toString() {
String start = startDate == null ? "null" : startDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
String end = endDate == null ? "null" : endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
StringBuilder sb = new StringBuilder();
sb.append(start).append(" ").append(end);
return sb.toString();
}
}
通过这样做,您可以轻松地调用 Collections.sort(list);
并按 startDate
:
对数据进行排序
public class SomeObjectSorting {
public static void main(String[] args) {
SomeObject object1 = new SomeObject(LocalDate.parse("2015-01-01"), null);
SomeObject object2 = new SomeObject(LocalDate.parse("2014-01-01"), LocalDate.parse("2017-01-01"));
SomeObject object3 = new SomeObject(LocalDate.parse("2016-01-01"), null);
List<SomeObject> list = Arrays.asList(object1, object2, object3);
System.out.println("———— BEFORE SORTING ————");
list.forEach(object -> {
System.out.println(object.toString());
});
Collections.sort(list);
System.out.println("———— AFTER SORTING ————");
list.forEach(object -> {
System.out.println(object.toString());
});
}
}
正如您提到的,您并不关心是 startDate
还是 endDate
,只是全部订购,也许以下内容会对您有所帮助:
List<LocalDate> dates = list.stream()
.flatMap(s -> Stream.of(s.startDate, s.endDate))
.filter(Objects::nonNull) // maybe... if nulls are required too, then skip that part here... (but also check the sorting variant then); note that I use null now if the last date is reached (check the printing part for that)
.distinct()
.sorted() // natural order
// alternatively: natural order + nulls last
// .sorted(Comparator.nullsLast(Comparator.comparing(Function.identity())))
.collect(Collectors.toList());
// printing part:
IntStream.range(0, dates.size())
.mapToObj(i -> {
String from = Objects.toString(dates.get(i));
String upto = Objects.toString(i < dates.size() - 1 ? dates.get(i + 1) : null); // exchange null with the end date you are expecting
return from + " - " + upto;
})
.forEach(System.out::println);
编辑: 之前在您的一个样本上设置了 endDate...现在情况不再如此,这里更新了如何设置正确的日期范围。它基本上类似于 Ralf Renz 在他的回答中使用的内容:
list.sort(Comparator.comparing(SomeObject::getStartDate));
IntStream.range(0, list.size() - 1)
.forEach(i -> list.get(i).endDate = list.get(i + 1).startDate);
// or if you care about performance, just do the same as Ralf did:
for (int i = 0; i < (list.size() - 1); i++) {
list.get(i).endDate = list.get(i + 1).startDate;
}
作为已接受答案的补充:
Collections.sort(list, Comparator.comparing(SomeObject::getStartDate));
我有一个包含两个 LocalDate 属性的对象:
public class SomeObject {
private LocalDate startDate;
private LocalDate endDate;
}
为简洁起见省略了构造函数和内容。我想按开始日期对这些对象的列表进行排序,然后将下一个对象的开始日期分配给前一个对象的结束日期。为了澄清,我从这些对象的列表开始:
SomeObject object1 = new SomeObject(LocalDate.parse("2015-01-01"), null);
SomeObject object2 = new SomeObject(LocalDate.parse("2014-01-01"), null);
SomeObject object3 = new SomeObject(LocalDate.parse("2016-01-01"), null);
List<SomeObject> list = Arrays.asList(object1, object2, object3);
排序后应该return这样:
for (SomeObject object : list) {
System.out.println(object.startDate.toString() + " " + object.endDate.toString() );
}
2014-01-01 2015-01-01
2015-01-01 2016-01-01
2016-01-01 null
每个列表最多只包含 3 或 4 个这样的对象,但代码可能必须处理数万个这样的列表,因此我正在寻找一种有效的方法来执行此操作。
您可以将 Collections.sort 与比较器一起使用。在使用 Lambdas 的 Java 8 中,它看起来像这样:
Collections.sort(list, (x, y) -> x.startDate.compareTo(y.startDate));
for (int i = 0; i < (list.size() - 1); i++) {
list.get(i).endDate = list.get(i + 1).startDate;
}
利用 LocalDate
已经 implements Comparable
这一事实,让你的 SomeObject
也这样做。此外,给它一个适当的 toString()
方法,它处理 null
值,以便将您的对象表示为 String
:
public class SomeObject implements Comparable<SomeObject> {
private LocalDate startDate;
private LocalDate endDate;
public SomeObject(LocalDate startDate, LocalDate endDate) {
this.startDate = startDate;
this.endDate = endDate;
}
@Override
public int compareTo(SomeObject anotherObject) {
return this.startDate.compareTo(anotherObject.startDate);
}
@Override
public String toString() {
String start = startDate == null ? "null" : startDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
String end = endDate == null ? "null" : endDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
StringBuilder sb = new StringBuilder();
sb.append(start).append(" ").append(end);
return sb.toString();
}
}
通过这样做,您可以轻松地调用 Collections.sort(list);
并按 startDate
:
public class SomeObjectSorting {
public static void main(String[] args) {
SomeObject object1 = new SomeObject(LocalDate.parse("2015-01-01"), null);
SomeObject object2 = new SomeObject(LocalDate.parse("2014-01-01"), LocalDate.parse("2017-01-01"));
SomeObject object3 = new SomeObject(LocalDate.parse("2016-01-01"), null);
List<SomeObject> list = Arrays.asList(object1, object2, object3);
System.out.println("———— BEFORE SORTING ————");
list.forEach(object -> {
System.out.println(object.toString());
});
Collections.sort(list);
System.out.println("———— AFTER SORTING ————");
list.forEach(object -> {
System.out.println(object.toString());
});
}
}
正如您提到的,您并不关心是 startDate
还是 endDate
,只是全部订购,也许以下内容会对您有所帮助:
List<LocalDate> dates = list.stream()
.flatMap(s -> Stream.of(s.startDate, s.endDate))
.filter(Objects::nonNull) // maybe... if nulls are required too, then skip that part here... (but also check the sorting variant then); note that I use null now if the last date is reached (check the printing part for that)
.distinct()
.sorted() // natural order
// alternatively: natural order + nulls last
// .sorted(Comparator.nullsLast(Comparator.comparing(Function.identity())))
.collect(Collectors.toList());
// printing part:
IntStream.range(0, dates.size())
.mapToObj(i -> {
String from = Objects.toString(dates.get(i));
String upto = Objects.toString(i < dates.size() - 1 ? dates.get(i + 1) : null); // exchange null with the end date you are expecting
return from + " - " + upto;
})
.forEach(System.out::println);
编辑: 之前在您的一个样本上设置了 endDate...现在情况不再如此,这里更新了如何设置正确的日期范围。它基本上类似于 Ralf Renz 在他的回答中使用的内容:
list.sort(Comparator.comparing(SomeObject::getStartDate));
IntStream.range(0, list.size() - 1)
.forEach(i -> list.get(i).endDate = list.get(i + 1).startDate);
// or if you care about performance, just do the same as Ralf did:
for (int i = 0; i < (list.size() - 1); i++) {
list.get(i).endDate = list.get(i + 1).startDate;
}
作为已接受答案的补充:
Collections.sort(list, Comparator.comparing(SomeObject::getStartDate));