从Collection中删除对象时出现IllegalStateException

时间:2017-06-23 13:31:57

标签: java arraylist contains

我正在遍历一个arrayList并删除适用于某些条件的项目。

library(shiny)

ui <- fluidPage(
  actionButton("btn", "click me")
)

server <- function(input, output)
{
  withWarnings <- function(expr) {
    myWarnings <- NULL
    wHandler <- function(w) {
      myWarnings <<- c(myWarnings, list(w))
      invokeRestart("muffleWarning")
    }
    val <- withCallingHandlers(expr, warning = wHandler)
    list(value = val, warnings = myWarnings)
  } 

  observeEvent(input$btn, {
    x <- withWarnings(1:3 * 1:2)
    if (!is.null(x$warnings)) {
      for (w in x$warnings) showNotification(w$message)

    }
  })
}

runApp(list(ui=ui, server=server))

为什么第一个陈述有效:

public static ArrayList<String> filteredArrayList(HashMap<String, Boolean> filters){

    ArrayList<String> filteredArrayList = new ArrayList<>();
    filteredArrayList = fullList();

    Iterator<String> i = filteredArrayList.iterator();
    while (i.hasNext()) {
        String s = i.next();

        if(!(filters.get("sometextStatus")) && (s.toLowerCase().trim().contains("sometext".trim().toLowerCase()))){
                i.remove();
        }
        if(!(filters.get("120Status")) && (s.toLowerCase().trim().contains("120".trim().toLowerCase()))){
                i.remove();
        }
    }
}

但第二个失败了吗?

if(!(filters.get("sometextStatus")) && (s.toLowerCase().trim().contains("sometext".trim().toLowerCase()))){
    i.remove();
}

我得到了:

  

线程中的异常&#34; main&#34; java.lang.IllegalStateException

为第二个。

3 个答案:

答案 0 :(得分:3)

public static ArrayList<String> filteredArrayList(HashMap<String, Boolean> filters){

    ArrayList<String> filteredArrayList = fullList(); //Note, that fullList method already creates and returns array, so you don't need to create it before calling this method.

    Iterator<String> i = filteredArrayList.iterator();
    while (i.hasNext()) {
        String s = i.next();

        if(!(filters.get("sometextStatus")) && (s.toLowerCase().trim().contains("sometext".trim().toLowerCase()))){
                i.remove();
                continue; //We removed current element, so next if check might potentially removed already removed element!
        }

        if(!(filters.get("120Status")) && (s.toLowerCase().trim().contains("120".trim().toLowerCase()))){
                i.remove();
                continue; //Maybe a programmer will decide to copy-paste if checks, so it is safer to do so with continue.
        }
    }
}

<强>更新

调试后,我找到了

Exception in thread "main" java.lang.NullPointerException
    at com.ca.training.jdk.loops.Main2.filteredArrayList(Main2.java:34)
    at com.ca.training.jdk.loops.Main2.main(Main2.java:14)

问题在于,如果

 filters.get("120Status")

返回 NULL ,这是可能的!?所以添加一个空检查

Boolean status1 = filters.get("sometextStatus");
if((status1 != null && status1) && (s.toLowerCase().trim().contains("sometext".trim().toLowerCase()))) {
    i.remove();
}

关键字continue使程序继续循环使用新的循环参数。因此,当第一个if语句为真时,我们不会进行第二次if检查,而是使用下一个i值继续循环执行。

<强>建议

尽可能使用基类或接口而不是子类。

  public static ArrayList<String> filteredArrayList(Map<String, Boolean> filters){ //Note, map

  List<String> filteredArrayList = fullList(); //Note, list.

答案 1 :(得分:0)

我猜第一个i.remove()已经删除了该元素。当第二次检查也匹配时,第二个i.remove()不再可能,而是抛出异常。只要您拨打continue;,就可以使用i.remove()

continue将跳转到循环的下一个元素。

但是,如果您要发布出现异常的确切代码行,这将更容易找到。

答案 2 :(得分:0)

如果你使用Java8,这可能会有所帮助。

在检查内容时,您不需要trim()该项目,而不是完全匹配。

如果您匹配该号码,也不需要lowerCase()

简单的lambda删除项目:

filteredArrayList.removeIf(s ->
                s.contains("123")
             || s.toLowerCase().contains("asd".toLowerCase())
             || s.toLowerCase().contains("something else".toLowerCase())
             || s.toLowerCase().contains("something else".toLowerCase())
        );

s是列表中的项目,您可以根据需要调用它 - 它是迭代器的项目是。