为什么这个for循环遍历ArrayList会在IntelliJ中生成“for语句不循环”的警告

时间:2016-12-23 16:55:53

标签: java for-loop intellij-idea break

我有ArrayList,其中包含Staff类的实例。当我写下面的代码时,IntelliJ告诉我'for语句不循环':

public String getTypist() {
    String tempTy = "";
    for (Staff g : staffList) {
        if (g.getStaffID().contains("TY") && g.isAvailable()){
            tempTy = g.getStaffID();
        }
        staffList.remove(g);
        staffWorking.add(g);
        break;
    }

    return tempTy;
}

我真的很困惑,因为我认为这是在for上正确使用ArrayList循环的方法。我在for循环中做错了什么?

2 个答案:

答案 0 :(得分:1)

你的for循环包含一个break语句,无论循环之前发生了什么,它总是会执行,因此在第一次循环发生后,break发生,没有别的之后循环这基本上使得它好像根本没有for循环,因为执行代码一次是执行一系列语句的默认方式。更正此问题涉及确保break仅执行某些循环(具体而言,确保它仅在您想要成为最后一个循环的循环上执行)。通过添加一些其他修正来进行更正,您将获得与此类似的代码:

public String getTypist() {
    for (Staff s : staffList) {
        if (s.getStaffID().contains("TY") && s.isAvailable()){
            staffList.remove(s);
            staffWorking.add(s);
            return s.getStaffID();
        }
    }

    return "";
}

但是,有一种替代解决方案可以让您避免迭代ArrayList。您可以使用此代码替换该代码,它将在没有任何for循环的情况下工作,因为它使用ArrayList本身的方法来完成任务:

public String getTypist() {
    ArrayList<Staff> staffWorking = new ArrayList<>(staffList);        
    staffWorking.removeIf(staff -> !(staff.isAvailable() && staff.getStaffID().contains("TY")));

    staffList.removeAll(staffWorking);

    Optional<Staff> typist = staffWorking.stream().findFirst();
    if(typist.isPresent()){
        return typist.getStaffID();
    }else{
        return "";
    }
}

虽然可以简化并改进(此代码支持并发过滤,因此在多处理器系统上会更快):

private static final Predicate<Staff> isATypistWorker = 
    staff -> staff.isAvailable() && staff.getStaffID().contains("TY");

public String getTypist() {
    ArrayList<Staff> typistWorkers = staffList.stream()
         .parallel()
         .filter(isATypistWorker)
         .distinct()
         .collect(Collectors.toCollection(ArrayList::new));

    staffList.removeAll(typistWorkers);
    staffWorkers.addAll(typistWorkers);

    Optional<Staff> typist = typistWorkers.stream().findFirst();

    return typist.isPresent() ? typist.getStaffID() : "";
}

答案 1 :(得分:0)

你没有循环,因为你在循环的第一次迭代后总是break。我认为您需要围绕if声明提供支持。

public String getTypist() {
    String tempTy = "";

    for (Staff g : staffList) {
        if (g.getStaffID().contains("TY") && g.isAvailable()) {
            tempTy = g.getStaffID();
            staffList.remove(g);
            staffWorking.add(g);
            break;
        }
    }

    return tempTy;
}

此外,我发布的代码无法正常工作,因为您无法在循环播放ArrayList时将其删除。但这是一个不同的问题。