简体   繁体   中英

Need to remove elements from an ArrayList of ArrayLists<Double>

I have code that processes wav files and sorts collections of double values (audio samples) into an ArrayList and each of these ArrayLists is then sorted into an ArrayList of ArrayLists:

ArrayList<Double> sampleEvent = new ArrayList<Double>();

ArrayList<ArrayList<Double>> EventsCollect = new ArrayList<ArrayList<Double>>();

I have code that attempts to remove ArrayLists that are less than a certain size from the collection.

However all it seems to do is half the list and doesn't remove the correct ArrayLists from the collection.

Please see my code below:

for (int loop = 0 ;   loop <  EventsCollect.size(); loop++) {
    if ( EventsCollect.get(loop).size() <  200000) {
         EventsCollect.remove(loop);
    }
}

After doing this, ArrayLists remain in the collection that are only triple figures in size.

Any advice about how to correct this would be greatly appreciated.

Your problem is that you increment the loop counter even if you remove an element. By doing this, you skip an element in the loop. Just change your if statement:

    int loop = 0; // loop counter
    while (loop < EventsCollect.size()) {
        if (EventsCollect.get(loop).size() < 200000) {
            EventsCollect.remove(loop);
        }
        else
            loop++;
    }

Or you can loop backwards through the ArrayList:

for (int i = EventsCollect.size() - 1; i >= 0; i --){
    if (EventsCollect.get(i).size() > 200000)
        EventsCollect.remove(i);
}

This works because you will always loop through the array a constant amount of time. If you look at your code, EventsCollect.size() changes as you remove elements, thus not looping through every element. This should be your cue that something is wrong.

in java 8, you can try removing with predicate using lambda expressions

    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()); 

as a side note, you might want to rename EventsCollect to eventsCollect (small letter e).

anyway, the reason why only half of your entries are evaluate is because when you delete an entry, all the bottom gets shifted up by one. the effect of this is that the first item of the newly shifted entry will not be evaluated.

assume we have 4 entries, and i is currently at 1 (pointing to 100k)

{230k, 100k, 20k, 122k} 

the loop evaluates and removes 100k

{230, 20k, 122k}

now all the values are shifted up by one, and i is incremented to 2 (pointing at 122k). notice that 20k is in the position of 1, and is now skipped. the loop will evaluate and remove 122k instead.

{230, 20k}

to fix your code with minimum changes, you need to do a reverse iteration (from last entry to the first)

for (int loop = EventsCollect.size()-1 ;   loop >=0; loop--) {
    if ( EventsCollect.get(loop).size() <  200000) {
         EventsCollect.remove(loop);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM