JTable按平均分排序后如何正确生成学生排名?
解决JTable排序后排名不正确的问题
嗨,我来帮你分析下问题所在,并且给出修复方案:
核心问题根源
你使用TableRowSorter实现的是**视图层(JTable显示的行)的排序,但你的positionInsert方法直接操作的是底层TableModel(原始数据顺序)**的行。这就导致你设置的排名是按照原始数据的顺序生成的,和JTable排序后显示的行顺序完全不匹配,自然出现排名错误。
修复后的代码
你需要通过JTable提供的索引转换方法,将视图层的行索引映射到底层模型的行索引,这样才能给排序后显示的每一行正确设置排名:
// 按平均分列排序JTable public void checkPosition(){ // 隐藏序号列 jTable1.getColumnModel().getColumn(0).setMinWidth(0); jTable1.getColumnModel().getColumn(0).setMaxWidth(0); jTable1.getColumnModel().getColumn(0).setWidth(0); TableRowSorter<TableModel> sorter = new TableRowSorter<>(jTable1.getModel()); jTable1.setRowSorter(sorter); List<RowSorter.SortKey> sortKeys = new ArrayList<>(); // 按平均分列(倒数第二列)降序排序 sortKeys.add(new RowSorter.SortKey(jTable1.getColumnCount()-2, SortOrder.DESCENDING)); sorter.setSortKeys(sortKeys); // 确保排序完成后再插入排名 sorter.sort(); positionInsert(); } public void positionInsert(){ // 在最后一列“position”插入排名 int pos = 1; DefaultTableModel model = (DefaultTableModel)jTable1.getModel(); // 遍历视图层的行(排序后的显示顺序) for(int viewRow = 0; viewRow < jTable1.getRowCount(); viewRow++){ // 将视图行索引转换为对应的模型行索引 int modelRow = jTable1.convertRowIndexToModel(viewRow); // 给模型中对应的行设置排名 model.setValueAt(pos, modelRow, jTable1.getColumnCount()-1); pos++; } }
关键细节解释
- 索引转换:
jTable1.convertRowIndexToModel(viewRow)方法的作用是把当前JTable显示的第viewRow行,映射到底层TableModel中对应的行索引。这样就能保证我们给排序后显示的每一行,正确地设置对应的排名。 - 提前获取模型:把
DefaultTableModel model = (DefaultTableModel)jTable1.getModel();移到循环外面,避免每次循环都重复获取模型,提升效率。 - 确保排序完成:调用
sorter.sort()显式触发排序,避免在排序还没完成时就执行排名插入操作。
额外优化(可选)
如果需要处理同分同排名的场景(比如两个学生平均分相同,排名应该一致),你可以在遍历视图行时,先获取当前行和上一行的平均分进行对比:
public void positionInsert(){ int pos = 1; DefaultTableModel model = (DefaultTableModel)jTable1.getModel(); // 记录上一行的平均分 double prevScore = -1; int sameCount = 0; for(int viewRow = 0; viewRow < jTable1.getRowCount(); viewRow++){ int modelRow = jTable1.convertRowIndexToModel(viewRow); double currentScore = Double.parseDouble(model.getValueAt(modelRow, jTable1.getColumnCount()-2).toString()); if(viewRow > 0 && currentScore == prevScore){ // 和上一行分数相同,排名不变 sameCount++; } else { // 分数不同,更新排名 pos += sameCount; sameCount = 0; } model.setValueAt(pos, modelRow, jTable1.getColumnCount()-1); prevScore = currentScore; } }
内容的提问来源于stack exchange,提问作者Heizy
相关产品推荐
相关产品推荐

