使用Comparator排序ArrayList时触发ClassCastException问题求助
嘿,先给你吃个定心丸:完全不需要让Vehicle实现Comparable接口!你用自定义Comparator的思路是对的,这玩意儿就是用来帮咱们不用修改原类就能实现自定义排序的。
咱们来看你遇到的错误栈,关键信息是这句:
java.lang.ClassCastException: class simulator.model.Vehicle cannot be cast to class java.lang.Comparable
为啥会出现这个?因为当你调用ArrayList.sort(Comparator c)的时候,如果传入的c是null,ArrayList会自动切换成自然排序模式——这时候就要求集合里的元素必须实现Comparable接口,而你的Vehicle没做这件事,所以就炸了。
那问题大概率出在你的_vehicleComparator变量上:你只是声明了这个属性,但没给它初始化实例!比如你在Road类里可能只写了:
private CompareVehicles _vehicleComparator;
但从来没执行过_vehicleComparator = new CompareVehicles();,导致调用_vehicles.sort(_vehicleComparator)时传进去的是null,触发了自然排序的逻辑,才抛出了这个异常。
怎么解决?
很简单,给你的Comparator实例化就行:
- 可以在Road的构造方法里初始化:
public Road(/* 你的构造参数 */) { // 其他初始化代码 this._vehicleComparator = new CompareVehicles(); } - 或者直接在声明的时候初始化:
private CompareVehicles _vehicleComparator = new CompareVehicles();
另外,顺便给你提个优化建议:你的内部类Comparator写得没问题,但其实可以用lambda表达式简化,代码会清爽很多,还能避免这种忘记初始化的坑:
// 直接在sort方法里传入lambda,不用单独写内部类 _vehicles.sort((o1, o2) -> { if (o1.getLocation() < o2.getLocation()) return 1; if (o1.getLocation() > o2.getLocation()) return -1; return 0; }); // 如果你的location是数值类型(比如int、double),还能更简洁: _vehicles.sort(Comparator.comparingDouble(Vehicle::getLocation).reversed());
这样写完,直接调用sort就完事,不用再维护单独的Comparator属性啦~
内容的提问来源于stack exchange,提问作者Awacate

