如何实现对读取自文本文件的国家ArrayList按人口、面积排序?
解决方案:封装实体类+自定义Comparator实现多维度排序
你当前的代码直接把每行文本作为字符串存入列表,虽然能快速实现名称排序,但要按人口、面积这类数值排序就会很麻烦——因为得先从字符串里拆分出数字,还容易出错。更好的做法是先把国家数据封装成一个实体类,再利用Comparator来定义不同的排序规则,这样代码更清晰、易维护。
步骤1:创建Land实体类
先定义一个类来封装国家的所有属性,这样我们能直接操作人口、面积这些数值:
public class Land { private String name; private long population; // 人口用long避免溢出 private int area; private String capital; // 构造方法 public Land(String name, long population, int area, String capital) { this.name = name; this.population = population; this.area = area; this.capital = capital; } // 必须的getter方法,用于排序时获取属性 public String getName() { return name; } public long getPopulation() { return population; } public int getArea() { return area; } public String getCapital() { return capital; } // 重写toString,方便输出格式和原文件一致 @Override public String toString() { return String.format("%s %d %d %s", name, population, area, capital); } }
步骤2:重构文件读取方法
把原来读取字符串列表的逻辑改成读取并生成Land对象列表,同时处理可能的格式异常:
private static ArrayList<Land> readLandsFromFile() { ArrayList<Land> lands = new ArrayList<>(); File file = new File("europa.txt"); // 使用try-with-resources自动关闭Scanner,避免资源泄漏 try (Scanner scan = new Scanner(file)) { while (scan.hasNextLine()) { String line = scan.nextLine(); String[] parts = line.split(" "); // 拆分后转换为对应类型(注意:如果国家名称含空格,需要调整拆分逻辑) String name = parts[0]; long population = Long.parseLong(parts[1]); int area = Integer.parseInt(parts[2]); String capital = parts[3]; lands.add(new Land(name, population, area, capital)); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (NumberFormatException e) { System.err.println("文件数据格式错误:" + e.getMessage()); } return lands; }
步骤3:实现按人口/面积排序
利用Collections.sort()配合Comparator,可以轻松定义不同的排序规则,支持升序/降序:
按人口排序(升序/降序)
// 人口升序(从少到多) public static void sortByPopulationAscending() { ArrayList<Land> lands = readLandsFromFile(); Collections.sort(lands, Comparator.comparingLong(Land::getPopulation)); printLands(lands); } // 人口降序(从多到少) public static void sortByPopulationDescending() { ArrayList<Land> lands = readLandsFromFile(); Collections.sort(lands, Comparator.comparingLong(Land::getPopulation).reversed()); printLands(lands); }
按面积排序(升序/降序)
// 面积升序(从小到大) public static void sortByAreaAscending() { ArrayList<Land> lands = readLandsFromFile(); Collections.sort(lands, Comparator.comparingInt(Land::getArea)); printLands(lands); } // 面积降序(从大到小) public static void sortByAreaDescending() { ArrayList<Land> lands = readLandsFromFile(); Collections.sort(lands, Comparator.comparingInt(Land::getArea).reversed()); printLands(lands); }
步骤4:通用打印方法
把打印逻辑抽出来,避免重复代码:
private static void printLands(List<Land> lands) { System.out.println("Country: Inhabitants: Size: Capital: "); for (Land land : lands) { System.out.println(land); } }
测试调用
在main方法里可以自由调用这些排序方法:
public static void main(String[] args) { System.out.println("=== 按名称排序 ==="); // 你原来的名称排序也可以用同样方式重构 ArrayList<Land> nameSortedLands = readLandsFromFile(); Collections.sort(nameSortedLands, Comparator.comparing(Land::getName)); printLands(nameSortedLands); System.out.println("\n=== 按人口升序排序 ==="); sortByPopulationAscending(); System.out.println("\n=== 按面积降序排序 ==="); sortByAreaDescending(); }
额外说明
- 如果你的文件里有名称含空格的国家(比如"United Kingdom"),直接用
split(" ")会拆分错误,这时候可以考虑按固定位置截取,或者用正则表达式匹配数字来拆分。 - 用
Comparator.comparingXXX是Java 8+的简洁写法,如果你用的是更早版本,可以用匿名内部类实现Comparator,比如:Collections.sort(lands, new Comparator<Land>() { @Override public int compare(Land l1, Land l2) { return Long.compare(l1.getPopulation(), l2.getPopulation()); } });
内容的提问来源于stack exchange,提问作者jossann
相关产品推荐
相关产品推荐

