我有处理wav文件的代码,并将双精度值(音频样本)的集合排序到ArrayList中,然后将每个ArrayLists排序到ArrayLists的ArrayList中:
ArrayList<Double> sampleEvent = new ArrayList<Double>();
ArrayList<ArrayList<Double>> EventsCollect = new ArrayList<ArrayList<Double>>();
我有一些代码尝试从集合中删除小于特定大小的ArrayList。
但是,它似乎只做列表的一半,并且没有从集合中删除正确的ArrayList。
请在下面查看我的代码:
for (int loop = 0 ; loop < EventsCollect.size(); loop++) {
if ( EventsCollect.get(loop).size() < 200000) {
EventsCollect.remove(loop);
}
}
完成此操作后,ArrayList保留在集合中,大小仅为三位数。
任何有关如何纠正此问题的建议将不胜感激。
答案 0 :(得分:2)
您的问题是,即使删除了元素,您也会增加循环计数器。这样,您可以跳过循环中的元素。只需更改您的if语句:
int loop = 0; // loop counter
while (loop < EventsCollect.size()) {
if (EventsCollect.get(loop).size() < 200000) {
EventsCollect.remove(loop);
}
else
loop++;
}
或者您可以向后遍历ArrayList:
for (int i = EventsCollect.size() - 1; i >= 0; i --){
if (EventsCollect.get(i).size() > 200000)
EventsCollect.remove(i);
}
之所以起作用,是因为您将始终在数组中循环一定的时间。如果您查看代码,则EventsCollect.size()
会在删除元素时发生变化,因此不会循环
通过每个元素。这应该是您提示出问题的地方。
答案 1 :(得分:0)
在Java 8中,您可以尝试使用lambda表达式删除谓词
EventsCollect = EventsCollect.stream()
//we want to retain only samples with more than 200_000 count
.filter(sampleEvent -> sampleEvent.size() >= 200_000)
//we collect everything that we want back into our EventsCollect list
.collect(Collectors.toList());
作为旁注,您可能希望将EventsCollect重命名为eventsCollect(小写字母e)。
无论如何,仅评估一半条目的原因是因为当您 删除一个条目,所有底部都向上移一位。这样的效果是,新转移的条目的第一项将不会被评估。
假设我们有4个条目,而我目前为1(指向100k)
{230k, 100k, 20k, 122k}
循环评估并删除100k
{230, 20k, 122k}
现在所有值都上移一个,并且i递增到2(指向122k)。请注意,20k位于1的位置,现在被跳过。循环将评估并删除122k。
{230, 20k}
要用最少的更改来修复代码,您需要进行反向迭代(从最后一个条目到第一个条目)
for (int loop = EventsCollect.size()-1 ; loop >=0; loop--) {
if ( EventsCollect.get(loop).size() < 200000) {
EventsCollect.remove(loop);
}
}