如何从文本文件读取数据存入PriorityQueue并输出Top5最大值条目
问题分析
你的代码存在两个核心问题:
- 默认的
PriorityQueue<String>是按字符串字典序排序,而非每行末尾的数值大小排序,导致输出结果完全不符合预期。 - 直接将整行字符串存入队列,无法基于数值字段定制排序逻辑。
解决方案
我们需要让PriorityQueue按照每行的数值字段降序排序,若仅需最大的5条数据,用小顶堆维护固定大小队列会更高效(避免存储所有数据)。以下提供三种实现方式:
方式一:字符串拆分+自定义Comparator
直接拆分每行提取数值,定制排序规则:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.Comparator; import java.util.PriorityQueue; public class Top5Data { public static void main(String[] args) { // 按数值降序排序的PriorityQueue PriorityQueue<String> queue = new PriorityQueue<>((line1, line2) -> { int num1 = Integer.parseInt(line1.split("\\s+")[2]); int num2 = Integer.parseInt(line2.split("\\s+")[2]); // 降序:大的元素排在前面 return Integer.compare(num2, num1); }); String file = "data.txt"; String line; // try-with-resources自动关闭流 try (BufferedReader br = new BufferedReader(new FileReader(file))) { while ((line = br.readLine()) != null) { queue.offer(line); } } catch (IOException e) { System.err.println("读取文件失败:" + e.getMessage()); } // 输出前5条最大记录 System.out.println("数值最大的5条数据:"); int count = 0; while (!queue.isEmpty() && count < 5) { count++; System.out.println(count + ". " + queue.poll()); } } }
方式二:小顶堆优化内存(推荐)
数据量较大时,仅维护大小为5的小顶堆,堆顶是当前最小元素,最终堆内即为最大的5个元素:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.Comparator; import java.util.PriorityQueue; public class Top5DataOptimize { public static void main(String[] args) { // 小顶堆:堆顶为当前最小元素,队列最多存5个元素 PriorityQueue<String> minHeap = new PriorityQueue<>((line1, line2) -> { int num1 = Integer.parseInt(line1.split("\\s+")[2]); int num2 = Integer.parseInt(line2.split("\\s+")[2]); // 升序排序,堆顶是最小元素 return Integer.compare(num1, num2); }); String file = "data.txt"; String line; try (BufferedReader br = new BufferedReader(new FileReader(file))) { while ((line = br.readLine()) != null) { minHeap.offer(line); // 超过5个元素时,移除当前最小的堆顶元素 if (minHeap.size() > 5) { minHeap.poll(); } } } catch (IOException e) { System.err.println("读取文件失败:" + e.getMessage()); } // 小顶堆取出的是从小到大,倒序输出得到从大到小的结果 System.out.println("数值最大的5条数据:"); String[] top5 = new String[5]; int index = 4; while (!minHeap.isEmpty()) { top5[index--] = minHeap.poll(); } for (int i = 0; i < top5.length; i++) { System.out.println((i+1) + ". " + top5[i]); } } }
方式三:实体类封装(可读性更强)
业务逻辑复杂时,封装为实体类更清晰:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.Comparator; import java.util.PriorityQueue; // 封装每行数据的实体类 class DataRecord { private String name; private String date; private int value; public DataRecord(String name, String date, int value) { this.name = name; this.date = date; this.value = value; } public int getValue() { return value; } @Override public String toString() { return name + " " + date + " " + value; } } public class Top5DataWithClass { public static void main(String[] args) { // 按数值降序排序的队列 PriorityQueue<DataRecord> queue = new PriorityQueue<>( Comparator.comparingInt(DataRecord::getValue).reversed() ); String file = "data.txt"; String line; try (BufferedReader br = new BufferedReader(new FileReader(file))) { while ((line = br.readLine()) != null) { String[] parts = line.split("\\s+"); DataRecord record = new DataRecord(parts[0], parts[1], Integer.parseInt(parts[2])); queue.offer(record); } } catch (IOException e) { System.err.println("读取文件失败:" + e.getMessage()); } System.out.println("数值最大的5条数据:"); int count = 0; while (!queue.isEmpty() && count < 5) { count++; System.out.println(count + ". " + queue.poll()); } } }
预期输出
运行任意一种方式,都会得到正确的Top5结果:
1. WHguJUYeLBYoton 1987-11-24 9664 2. uecbYlaCeaTSAsr 1937-4-1 9305 3. amHPTQXCqHkYtXW 1991-8-24 8778 4. dMGDWfIrPctuwBs 2005-3-15 8567 5. ZsvJcYbmOFmdXfG 1923-10-10 8314
内容的提问来源于stack exchange,提问作者TheMurteza
相关产品推荐
相关产品推荐

