【异常总结】集合(Set)对象遍历遇到的空指针异常

1、遍历有值的Set集合,做了remove操作

Set groupNames = new TreeSet<>();
……
List exist = listGroupByNames(dto).getData();

// 去除已存在分组
if (CheckUtil.isNotNullAndNotEmpty(exist)) {
    for (String tmp : groupNames) {
        for (GroupResDTO eDto : exist) {
            if (tmp.equals(eDto.getGroupName())) {
                groupNames.remove(tmp);
            }
        }
    }
}

由于遍历的是groupNames对象,而又在符合条件的时候将groupNames 中的内容移除导致下一次循环的时候抛出空指针异常。解决方法是遍历对象为groupNames 的复制对象:

Set newSet = new HashSet<>(groupNames);
if (CheckUtil.isNotNullAndNotEmpty(exist)) {
    for (String tmp : newSet ) {
        for (GroupResDTO eDto : exist) {
            if (tmp.equals(eDto.getGroupName())) {
                groupNames.remove(tmp);
            }
        }
    }
}

新的解决方法(感谢评论中大佬的建议)
使用迭代器遍历并更改了遍历顺序(先遍历比对的对象A,再遍历需要做remove操作的对象B)。

如果采用的先遍历B再遍历A的顺序会导致遍历不完全。原因当迭代器对象it进行了remove操作之后,it.next()立马就变了,而此时还在A的遍历循环里面,出现A的第一次遍历还没完成,it.next()值已经变了的情况,继而会用新的it.next()比对A的下一个对象,整个双重循环就被破坏了。

因而改变了遍历顺序,这样可以保证双重循环稳定性。代码如下:

if (CheckUtil.isNotNullAndNotEmpty(exist)) {
    for (GroupResDTO eDto : exist) {
        // 获取容器指针,此时指针指向第一个元素的前面(内置的一个空元素)
        Iterator it = groupNames.iterator();
       
        // hasNext仅判断,不移动指针
        while (it.hasNext()) {
            // next方法移动指针指向下一个,并返回指向的当前元素
            if (eDto.getGroupName().equals(it.next())) {
                // remove 合法移除指针指向的当前元素
                it.remove();
            }
        }
    }
}

以上代码简写如下:

if (CheckUtil.isNotNullAndNotEmpty(exist)) {
    for (GroupResDTO eDto : exist) {
        groupNames.removeIf(s -> eDto.getGroupName().equals(s));
    }
}

2、遍历空集合对象

你可能感兴趣的:(Exception)