我想对我的自定义对象进行排序,其中它有两个字段。1)平码(长)和2)滚动(字母数字)。我想按自然顺序对平码进行排序,但当它们相同时,我想按滚动号降序排序。
我使用的是Java 8比较器,我有以下代码。
型号:
public class AreaModel {
public long pinCode;
public String rollNo;
public AreaModel(long pinCode, String rollNo) {
super();
this.pinCode = pinCode;
this.rollNo = rollNo;
}
public long getPinCode() {
return pinCode;
}
public void setPinCode(long pinCode) {
this.pinCode = pinCode;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
@Override
public String toString() {
return "["+pinCode+" "+rollNo+"]";
}
}Main:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.javainuse.model.AreaModel;
public class MainClass {
public static void main(String[] args) {
List<AreaModel> list = new ArrayList<AreaModel>();
list.add(new AreaModel(535005, "2"));
list.add(new AreaModel(535006, "100"));
list.add(new AreaModel(535007, "30"));
list.add(new AreaModel(535005, "ROLE-45"));
list.add(new AreaModel(535005, "ROLE-10"));
list.add(new AreaModel(535005,"13"));
list.add(new AreaModel(535005,"70"));
Function<AreaModel, Long> retentionCodeSequence = AreaModel::getPinCode;
Function<AreaModel, String> retentionDuration = AreaModel::getRollNo;
// sort area by pincode, then by role
Comparator<AreaModel> lastThenFirst = Comparator.comparing(retentionCodeSequence).thenComparing(retentionDuration,Comparator.reverseOrder());
list= list.stream().sorted(lastThenFirst).collect(Collectors.toList());
System.out.println("***");
System.out.println(list);
}
}有了这个,我得到的输出就是
[535005角色-45,535005角色-10,535005 70,535005 2,535005 13,535006 100,535007 30]
我所期待的是
[535005 70,535005角色-45,535005 13,535005角色-10,535005 2,535006 100,535007 30]
正如您所看到的,即使已经排序,角色也没有。角色可以包含整个数字作为字符串,或者是以文本为后缀的数字。我该怎么解决呢?
编辑:使用字符串中可能的值更新的问题
发布于 2022-09-21 15:31:08
假设属性rollNo的所有有效值都具有格式"PREFIX-DIGITS",即它从一个可选前缀开始,包含一个非数字字符,后面跟着一个破折号,并以一个强制数字部分结尾,那么您可以构造一个下面的比较器,它分别处理数字部分和非数字部分。
Comparator<AreaModel> lastThenFirst =
Comparator.comparing(AreaModel::getPinCode)
.thenComparing(Comparator
.<AreaModel, String>comparing(area -> area.getRollNo().replaceAll("\\d", ""), Comparator.reverseOrder())
.thenComparing(area -> Integer.parseInt(area.getRollNo().replaceAll("\\D","")), Comparator.reverseOrder())
);注意到,当有几个AreaModel实例具有相同的pinCode,其中一个实例的rollNo值中没有非数字部分时,则该实例将是排序后的最后一个实例(在具有相同密码的组中)。如果需要相反的行为,则可以通过在链中再添加一个比较器来单独检查这种情况:
Comparator<AreaModel> lastThenFirst =
Comparator.comparing(AreaModel::getPinCode)
.thenComparing(
Comparator.<AreaModel, Boolean>comparing(area -> area.getRollNo().matches("\\d"))
.thenComparing(area -> area.getRollNo().replaceAll("\\d", ""), Comparator.reverseOrder())
.thenComparing(area -> Integer.parseInt(area.getRollNo().replaceAll("\\D", "")), Comparator.reverseOrder())
);发布于 2022-09-22 11:32:49
正如@g00se所提到的,角色中的整数值应该被解析并在比较器中使用。
此外,ToLongFunction可用于处理pinCode,默认的List::sort应用于对当前列表进行排序。
ToLongFunction<AreaModel> pinCode = AreaModel::getPinCode;
ToIntFunction<AreaModel> roleToInt = am -> Integer.parseInt(am.getRollNo().replaceAll("\\D", ""));
Comparator<AreaModel> byRoleDesc = Comparator.comparingInt(roleToInt).reversed();
// sort area by pincode, then by role
Comparator<AreaModel> byPinAndReversedRole = Comparator
.comparingLong(pinCode)
.thenComparing(byRoleDesc);
list.sort(byPinAndReversedRole);
// -> [[535005 70], [535005 ROLE-45], [535005 13], [535005 ROLE-10], [535005 2], [535006 100], [535007 30]]https://stackoverflow.com/questions/73803054
复制相似问题