如何对包含Car和Bus类对象的ArrayList按name属性字母排序?
按name属性排序的几种解决方法
针对你这种两个无继承关系但拥有同名属性的类,要对Object类型集合排序,有以下几种可行方案:
方案1:使用反射(无需修改原有类)
因为Car和Bus都有public的name属性,我们可以通过反射获取该属性的值,再进行字符串比较。这种方法不用改动已有的Car和Bus类,适合快速实现需求:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.lang.reflect.Field; public class SortVehicles { public static void main(String[] args) { ArrayList<Object> vehicles = new ArrayList<>(); vehicles.add(new Car("Fiat")); vehicles.add(new Car("Citroen")); vehicles.add(new Bus("Ford")); vehicles.add(new Bus("Toyota")); Collections.sort(vehicles, new Comparator<Object>() { @Override public int compare(Object o1, Object o2) { try { // 获取对象的name字段值 Field nameField1 = o1.getClass().getField("name"); String name1 = (String) nameField1.get(o1); Field nameField2 = o2.getClass().getField("name"); String name2 = (String) nameField2.get(o2); // 按字母顺序比较(忽略大小写,要区分大小写用compareTo) return name1.compareToIgnoreCase(name2); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); return 0; } } }); // 测试输出 for (Object vehicle : vehicles) { try { Field nameField = vehicle.getClass().getField("name"); System.out.println(nameField.get(vehicle)); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } } } // 原有的Car和Bus类 class Car { public String name; public Car(String name) { this.name = name; } } class Bus { public String name; public Bus(String name) { this.name = name; } }
方案2:定义共同接口(推荐,类型更安全)
这种方法需要修改Car和Bus类,让它们实现同一个包含getName()方法的接口,这样集合可以使用接口类型,排序时直接调用方法,避免反射的风险和类型转换问题:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; // 定义共同接口 interface Named { String getName(); } // 修改Car类实现接口 class Car implements Named { public String name; public Car(String name) { this.name = name; } @Override public String getName() { return name; } } // 修改Bus类实现接口 class Bus implements Named { public String name; public Bus(String name) { this.name = name; } @Override public String getName() { return name; } } public class SortVehicles { public static void main(String[] args) { // 改用Named类型的集合,类型更安全 List<Named> vehicles = new ArrayList<>(); vehicles.add(new Car("Fiat")); vehicles.add(new Car("Citroen")); vehicles.add(new Bus("Ford")); vehicles.add(new Bus("Toyota")); // 直接按getName()返回值排序 Collections.sort(vehicles, Comparator.comparing(Named::getName)); // 忽略大小写排序可替换为:Comparator.comparing(Named::getName, String.CASE_INSENSITIVE_ORDER) // 测试输出 for (Named vehicle : vehicles) { System.out.println(vehicle.getName()); } } }
方案3:使用instanceof类型判断(无反射,无需改类)
如果不想用反射,也不想修改原有类,可以在比较器里判断对象的类型,分别获取name属性:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class SortVehicles { public static void main(String[] args) { ArrayList<Object> vehicles = new ArrayList<>(); vehicles.add(new Car("Fiat")); vehicles.add(new Car("Citroen")); vehicles.add(new Bus("Ford")); vehicles.add(new Bus("Toyota")); Collections.sort(vehicles, new Comparator<Object>() { @Override public int compare(Object o1, Object o2) { String name1 = getName(o1); String name2 = getName(o2); return name1.compareToIgnoreCase(name2); } private String getName(Object obj) { if (obj instanceof Car) { return ((Car) obj).name; } else if (obj instanceof Bus) { return ((Bus) obj).name; } return ""; // 处理其他类型的默认值 } }); // 测试输出 for (Object vehicle : vehicles) { System.out.println(getName(vehicle)); } } private static String getName(Object obj) { if (obj instanceof Car) { return ((Car) obj).name; } else if (obj instanceof Bus) { return ((Bus) obj).name; } return ""; } } class Car { public String name; public Car(String name) { this.name = name; } } class Bus { public String name; public Bus(String name) { this.name = name; } }
方案对比
- 反射方案:无需修改原有类,但存在反射性能损耗,若类结构变化(如name字段改名)会抛出异常。
- 共同接口方案:类型安全、代码规范,是最优解,但需要修改原有类。
- instanceof方案:无反射、无需改类,但后续新增同类结构的类时,需修改比较器逻辑,扩展性较差。
内容的提问来源于stack exchange,提问作者seba123neo
相关产品推荐
相关产品推荐

