如何在遍历数组的同时删除元素

时间:2019-05-01 12:56:36

标签: java arrays java-8 java-stream

我有一个包含其他对象列表的对象,该对象包含另一个对象列表。非常像DTO。 在这些对象中,有一个其他类型的对象的列表,如果对象包含特定的String,我想在其中删除该元素。

例如

CustomerDTO customerDTO = CustomerTransformer.transformCustomer(custom);
List<InfoDTO> info = customerDTO.getInfo();
info(infoDTO -> {
    List<MoreDTO> d = infoDTO.getMore();
    for (MoreDTO moreDTO : d) {
        List<ChannelDTO> channels = MoreDTO.getChannels();
        for (ChannelDTO cdto : contentChannels) {
            if ("apple".equals(cdto.getId())) {
                moreDTO.getChannels().remove(cdto);
            }
        }
    }

});

但是,实际上这似乎并不高效,并且可能会更改null指针吗?有更好的书写方式吗?在流中使用流和使用过滤器会有所帮助吗?

我是Java的新手。

2 个答案:

答案 0 :(得分:2)

在迭代/循环时,您无法从列表中删除元素,会有一个ConcurrentModificationException

为避免这种情况,您可以通过这种方式在此处使用Java 8 Filter-

contentChannels = contentChannels
 .stream()
 .filter(cdto->(!"apple".equals(cdto.getId())))
 .collect(Collectors.toList());

另一个选择是使用removeIf()

答案 1 :(得分:2)

上面的代码不起作用,请参阅@JB Nizet注释,

Triggering a ConcurrentModificationException

  

从本质上讲,当我们迭代的内容被修改时,ConcurrentModificationException用来快速失败。让我们通过一个简单的测试来证明这一点:

List<Integer> integers = newArrayList(1, 2, 3);

for (Integer integer : integers) {
    integers.remove(1);
}

因此您可以使用forEachremoveIf来避免ConcurrentModificationException

List<InfoDTO> info = customerDTO.getInfo();
info.forEach(more->more.getMore().forEach(channelDto->channelDto.getChannels().removeIf(cdto->"apple".equals(cdto.getId()))));

或者如果您只有List<ChannelDTO>

List<ChannelDTO> channels = MoreDTO.getChannels();
channels.removeIf(cdto->"apple".equals(cdto.getId()));