如何解决JavaCollections.sort()比较方法违反其通用契约Exception
How to resolve Java Collections.sort() Comparison method violates its general contract Exception
我正在使用 Collections.sort 根据时间字段对列表进行升序排序。
下面是代码
private String getShipmentInpickingTime(List<Shipments> shipments) {
logger.info("in getShipmentInpickingTime");
DateFormat sdf = new SimpleDateFormat("hh:mm");
Collections.sort(shipments, (o1, o2) -> {
try {
if ((!"null".equals(o1.getShipmentinpickingtime())
&& !StringUtils.isEmpty(o1.getShipmentinpickingtime()))
&& (!"null".equals(o2.getShipmentinpickingtime())
&& !StringUtils.isEmpty(o2.getShipmentinpickingtime()))) {
return sdf.parse(o1.getShipmentinpickingtime()).compareTo(sdf.parse(o2.getShipmentinpickingtime()));
}
} catch (ParseException e) {
e.printStackTrace();
}
int count1 = 0;
return count1;
});
此方法抛出异常 --
java.lang.IllegalArgumentException: Comparison method violates its general contract.
我查看了关于此问题的 google - 它说我正在比较较大的对象和较小的对象。我试过颠倒对象的顺序,但没有成功。
如果任一 元素解析失败,您只会捕获一次异常。
考虑以下时间的三批货物:
A - 12:34
B - 34:56
C-空
使用您的比较器,compare(A, C)
将 return 0,compare(B, C)
将 return 0,但 compare(A, B)
将 return a non-zero结果,从而违反传递性一般契约。
一种简单的方法是使用 Comparator.comparing
语法分别解析每个元素:
DateFormat sdf = new SimpleDateFormat("hh:mm");
shipments.sort(Comparator.comparing(
Shipments::getShipmentinpickingtime,
Comparator.nullsLast(Comparator.comparing(time -> {
try {
if (!"null".equals(time) && !StringUtils.isEmpty(time)) {
return sdf.parse(time);
}
} catch (ParseException ignoe) {
// Not a valid time
}
return null;
})))
);
你没有提到是哪一行代码抛出这个错误。我不确定您在这里使用的是哪个 StringUtils,com.sun.deploy.util.StringUtils
没有 .isEmpty()
方法。所以我重新实现了它。
这是解决您的问题的有效代码:
public static void main(String[] args){
getShipmentInpickingTime(new ArrayList<Shipments>(){{
add(new Shipments("12:00"));
add(new Shipments("12:03"));
add(new Shipments("12:02"));
}});
}
private static void getShipmentInpickingTime(List<Shipments> shipments) {
DateFormat sdf = new SimpleDateFormat("hh:mm");
System.out.println(shipments.toString());
Collections.sort(shipments, (o1, o2) -> {
try {
if ((!"null".equals(o1.getShipmentPickingTime())
&& !(o1.getShipmentPickingTime() == null || o1.getShipmentPickingTime().length() < 1))
&& (!"null".equals(o2.getShipmentPickingTime())
&& !(o2.getShipmentPickingTime() == null || o2.getShipmentPickingTime().length() < 1))) {
return sdf.parse(o1.getShipmentPickingTime()).compareTo(sdf.parse(o2.getShipmentPickingTime()));
}
} catch (ParseException e) {
e.printStackTrace();
}
return 0;
});
System.out.println(shipments.toString());
}
出货量class内容:
public class Shipments {
private String shipmentPickingTime;
public Shipments(String shipmentPickingTime) {
this.shipmentPickingTime = shipmentPickingTime;
}
public String getShipmentPickingTime() {
return shipmentPickingTime;
}
public void setShipmentPickingTime(String shipmentPickingTime) {
this.shipmentPickingTime = shipmentPickingTime;
}
@Override
public String toString() {
return "Shipments{" +
"shipmentPickingTime='" + shipmentPickingTime + '\'' +
'}';
}
}
输出:
[Shipments{shipmentPickingTime='12:00'}, Shipments{shipmentPickingTime='12:03'}, Shipments{shipmentPickingTime='12:02'}]
[Shipments{shipmentPickingTime='12:00'}, Shipments{shipmentPickingTime='12:02'}, Shipments{shipmentPickingTime='12:03'}]
我正在使用 Collections.sort 根据时间字段对列表进行升序排序。 下面是代码
private String getShipmentInpickingTime(List<Shipments> shipments) {
logger.info("in getShipmentInpickingTime");
DateFormat sdf = new SimpleDateFormat("hh:mm");
Collections.sort(shipments, (o1, o2) -> {
try {
if ((!"null".equals(o1.getShipmentinpickingtime())
&& !StringUtils.isEmpty(o1.getShipmentinpickingtime()))
&& (!"null".equals(o2.getShipmentinpickingtime())
&& !StringUtils.isEmpty(o2.getShipmentinpickingtime()))) {
return sdf.parse(o1.getShipmentinpickingtime()).compareTo(sdf.parse(o2.getShipmentinpickingtime()));
}
} catch (ParseException e) {
e.printStackTrace();
}
int count1 = 0;
return count1;
});
此方法抛出异常 --
java.lang.IllegalArgumentException: Comparison method violates its general contract.
我查看了关于此问题的 google - 它说我正在比较较大的对象和较小的对象。我试过颠倒对象的顺序,但没有成功。
如果任一 元素解析失败,您只会捕获一次异常。
考虑以下时间的三批货物:
A - 12:34
B - 34:56
C-空
使用您的比较器,compare(A, C)
将 return 0,compare(B, C)
将 return 0,但 compare(A, B)
将 return a non-zero结果,从而违反传递性一般契约。
一种简单的方法是使用 Comparator.comparing
语法分别解析每个元素:
DateFormat sdf = new SimpleDateFormat("hh:mm");
shipments.sort(Comparator.comparing(
Shipments::getShipmentinpickingtime,
Comparator.nullsLast(Comparator.comparing(time -> {
try {
if (!"null".equals(time) && !StringUtils.isEmpty(time)) {
return sdf.parse(time);
}
} catch (ParseException ignoe) {
// Not a valid time
}
return null;
})))
);
你没有提到是哪一行代码抛出这个错误。我不确定您在这里使用的是哪个 StringUtils,com.sun.deploy.util.StringUtils
没有 .isEmpty()
方法。所以我重新实现了它。
这是解决您的问题的有效代码:
public static void main(String[] args){
getShipmentInpickingTime(new ArrayList<Shipments>(){{
add(new Shipments("12:00"));
add(new Shipments("12:03"));
add(new Shipments("12:02"));
}});
}
private static void getShipmentInpickingTime(List<Shipments> shipments) {
DateFormat sdf = new SimpleDateFormat("hh:mm");
System.out.println(shipments.toString());
Collections.sort(shipments, (o1, o2) -> {
try {
if ((!"null".equals(o1.getShipmentPickingTime())
&& !(o1.getShipmentPickingTime() == null || o1.getShipmentPickingTime().length() < 1))
&& (!"null".equals(o2.getShipmentPickingTime())
&& !(o2.getShipmentPickingTime() == null || o2.getShipmentPickingTime().length() < 1))) {
return sdf.parse(o1.getShipmentPickingTime()).compareTo(sdf.parse(o2.getShipmentPickingTime()));
}
} catch (ParseException e) {
e.printStackTrace();
}
return 0;
});
System.out.println(shipments.toString());
}
出货量class内容:
public class Shipments {
private String shipmentPickingTime;
public Shipments(String shipmentPickingTime) {
this.shipmentPickingTime = shipmentPickingTime;
}
public String getShipmentPickingTime() {
return shipmentPickingTime;
}
public void setShipmentPickingTime(String shipmentPickingTime) {
this.shipmentPickingTime = shipmentPickingTime;
}
@Override
public String toString() {
return "Shipments{" +
"shipmentPickingTime='" + shipmentPickingTime + '\'' +
'}';
}
}
输出:
[Shipments{shipmentPickingTime='12:00'}, Shipments{shipmentPickingTime='12:03'}, Shipments{shipmentPickingTime='12:02'}]
[Shipments{shipmentPickingTime='12:00'}, Shipments{shipmentPickingTime='12:02'}, Shipments{shipmentPickingTime='12:03'}]