[英]Java: sorting list of objects by substrings of a given String property (pattern ITEM/LOC/YYYY/N)
我有一个对象列表,我想通过 formNumber 属性对它们进行排序(升序和降序)。
FormNumber 始终是模式 ITEM/LOC/YYYY/N 的字符串,其中:
我想先按 YYYY 排序,然后如果等于 N,然后如果等于 LOC。
对象的数量可以是数百而不是数千。 最好/最有效的方法是什么?
首先,创建一个包装器 class:
class ObjWrapper implements Comparable<ObjWrapper> {
private static final Pattern DELIM = Pattern.compile("/");
Obj obj;
String[] formNumberSplit;
public ObjWrapper(Obj obj) {
this.obj = obj;
this.formNumberSplit = DELIM.split(obj.getFormNumber());
}
@Override
public int compareTo(ObjWrapper another) {
int compareYear = formNumberSplit[2].compareTo(another.formNumberSplit[2]);
if (compareYear != 0) {
return compareYear;
}
int compareN = Integer.compare(
Integer.parseInt(formNumberSplit[3]),
Integer.parseInt(another.formNumberSplit[3]));
if (compareN != 0) {
return compareN;
}
return formNumberSplit[1].compareTo(another.formNumberSplit[1]);
}
public Obj getObj() {
return obj;
}
}
它将进行拆分并帮助对我们的对象进行排序。 当然,代替Obj
的是您的 class。 然后进行排序:
List<Obj> sortedObjs = objsList.stream()
.map(ObjWrapper::new)
.sorted()
.map(ObjWrapper::getObj)
.collect(Collectors.toList());
我会创建三个比较器并在排序时将它们链接在一起。 它使您的代码更具可读性和明显性。 此外,您可以根据需要在降序和升序之间灵活切换各个属性的排序
例子:
List<String> list = new ArrayList<>();
list.add("ITEM/NYC/2020/3");
list.add("ITEM/TOR/2018/13");
list.add("ITEM/MIA/2020/41");
list.add("ITEM/NYC/2018/7");
list.add("ITEM/MIA/2018/11");
list.add("ITEM/NYC/2020/17");
list.add("ITEM/NYC/2019/13");
list.add("ITEM/MIA/2019/3");
list.add("ITEM/TOR/2019/3");
Comparator<String> byYear = (y1,y2)->
Integer.compare(Integer.parseInt(y1.split("/")[2]), Integer.parseInt(y2.split("/")[2]));
Comparator<String> byN = (n1,n2)->
Integer.compare(Integer.parseInt(n1.split("/")[3]), Integer.parseInt(n2.split("/")[3]));
Comparator<String> byLoc = (loc1,loc2)-> loc1.split("/")[1].compareTo(loc2.split("/")[1]);
// sort by all asc
list.sort(byYear.thenComparing(byN).thenComparing(byLoc));
list.forEach(System.out::println);
// sort by year desc, then by n asc and loc desc
list.sort(byYear.reversed().thenComparing(byN).thenComparing(byLoc).reversed());
// combine them as you wish or exclude one if not necessary etc...
如果排序顺序是固定的并且将来不会改变,您也可以将它们组合成一个比较器
编辑
假设您有一个带有 formNumber 属性的 class Foo :
class Foo{
String formNumber;
public String getFormNumber() {
return formNumber;
}
}
和一个 foos 列表:
List<Foo> fooList = ....
然后将上面的内容更改为:
Comparator<Foo> byYear = (y1,y2)->
Integer.compare(Integer.parseInt(y1.getFormNumber().split("/")[2]),
Integer.parseInt(y2.getFormNumber().split("/")[2]));
Comparator<Foo> byN = (n1,n2)->
Integer.compare(Integer.parseInt(n1.getFormNumber().split("/")[3]),
Integer.parseInt(n2.getFormNumber().split("/")[3]));
Comparator<Foo> byLoc = (loc1,loc2)-> loc1.getFormNumber().split("/")[1]
.compareTo(loc2.getFormNumber().split("/")[1]);
比较器的用法保持不变
fooList.sort(byYear.thenComparing(byN).thenComparing(byLoc));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.