You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的For循环忽略了满足条件的乘客分组元素?

乘客分组排序错误的原因与修复方案

问题背景

分组规则如下(优先级从高到低,1组在列表开头,8组在末尾,优先级编号103到1):

  • 1组:Type H
  • 2组:Type E 且 Row 1-4
  • 3组:Type G 且 Row 1-4
  • 4组:Type E 或(Type G 且 Row 10/11)
  • 5组:Type G 且 Row 23-26
  • 6组:Type G 且 Row 17-22
  • 7组:Type G 且 Row 11-16(Row11的G已被4组处理)
  • 8组:Type G 且 Row 5-10

核心错误原因

1. ArrayList正序遍历删除导致索引遗漏

所有分组循环采用正序遍历ArrayList并直接删除元素,会触发索引错位:删除i位置元素后,后续元素自动前移一位,但循环变量i继续自增,直接跳过了原本位于i+1位置的元素,导致该元素未被检查是否符合当前组条件。

比如Estes(Type E,Row7)本该属于第4组,但遍历第4组时,前面元素被删除后Estes的索引前移,却被循环变量跳过,最终被错误分到后续组。

2. 外层while循环的冗余执行

外层while (!list.isEmpty())会重复执行所有分组循环,第一次循环遗漏的元素,第二次执行时可能被错误匹配到前面组的条件,进一步打乱分组顺序(比如剩余Type E元素会被再次处理,但此时优先级编号已大幅降低)。

3. 部分分组条件的隐含漏洞

第4组的条件代码Type E || Row10 || Row11未明确限制Row10/11的元素必须是Type G,虽然当前数据不会出问题,但如果后续出现其他类型的Row10/11元素,会被错误分到第4组。

修复方案

方案1:使用迭代器安全遍历删除

迭代器是Java中遍历并删除集合元素的标准安全方式,不会出现索引错位:

public void loadOldPQ(ArrayList<Passenger> list) throws IOException {
    int priorityNumber = list.size();

    // 处理1组:Type H
    Iterator<Passenger> iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("H")) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    // 处理2组:Type E 且 Row1-4
    iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("E") && p.getRow() >= 1 && p.getRow() <= 4) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    // 处理3组:Type G 且 Row1-4
    iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 1 && p.getRow() <= 4) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    // 处理4组:Type E 或 (Type G 且 Row10/11)
    iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("E") || 
            (p.getType().equalsIgnoreCase("G") && (p.getRow() == 10 || p.getRow() == 11))) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    // 处理5组:Type G 且 Row23-26
    iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 23 && p.getRow() <= 26) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    // 处理6组:Type G 且 Row17-22
    iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 17 && p.getRow() <= 22) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    // 处理7组:Type G 且 Row11-16
    iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 11 && p.getRow() <= 16) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    // 处理8组:Type G 且 Row5-10
    iterator = list.iterator();
    while (iterator.hasNext()) {
        Passenger p = iterator.next();
        if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 5 && p.getRow() <= 10) {
            p.setKey(priorityNumber--);
            oldPQ.add(p);
            iterator.remove();
        }
    }

    oldProcedure(oldPQ);
}

方案2:倒序遍历ArrayList

如果不想使用迭代器,可采用倒序遍历,删除元素后不会影响前面未遍历的元素索引:

// 示例:处理1组的倒序遍历逻辑
for (int i = list.size() - 1; i >= 0; i--) {
    Passenger p = list.get(i);
    if (p.getType().equalsIgnoreCase("H")) {
        p.setKey(priorityNumber--);
        oldPQ.add(p);
        list.remove(i);
    }
}

方案3:基于优先级分组的排序优化

更简洁的方式是先给每个乘客分配组优先级,再通过排序完成分组,避免多次遍历删除:

public void loadOldPQ(ArrayList<Passenger> list) throws IOException {
    // 为每个乘客分配组优先级(组号越小,优先级越高)
    for (Passenger p : list) {
        int group;
        if (p.getType().equalsIgnoreCase("H")) {
            group = 1;
        } else if (p.getType().equalsIgnoreCase("E") && p.getRow() >= 1 && p.getRow() <= 4) {
            group = 2;
        } else if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 1 && p.getRow() <= 4) {
            group = 3;
        } else if (p.getType().equalsIgnoreCase("E") || (p.getType().equalsIgnoreCase("G") && (p.getRow() == 10 || p.getRow() == 11))) {
            group = 4;
        } else if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 23 && p.getRow() <= 26) {
            group = 5;
        } else if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 17 && p.getRow() <= 22) {
            group = 6;
        } else if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 11 && p.getRow() <= 16) {
            group = 7;
        } else if (p.getType().equalsIgnoreCase("G") && p.getRow() >= 5 && p.getRow() <= 10) {
            group = 8;
        } else {
            group = 9; // 异常情况默认最低优先级
        }
        p.setKey(100 - group); // 用组号映射临时优先级,后续再调整为连续编号
    }

    // 按临时优先级降序排序
    Collections.sort(list, (a, b) -> Integer.compare(b.getKey(), a.getKey()));

    // 重新赋值连续的优先级编号103到1
    int priority = 103;
    for (Passenger p : list) {
        p.setKey(priority--);
        oldPQ.add(p);
    }

    oldProcedure(oldPQ);
}

内容的提问来源于stack exchange,提问作者fkaman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:37:08