Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Removing Items From ArrayLists in Java 8

DZone's Guide to

Removing Items From ArrayLists in Java 8

Can Java 8 beat the usual cost of removing items from an ArrayList? Read on to find out and for some source code.

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

As we know, ArrayList's implementation of the List interface stores elements in an Array under the hood. Removing elements from an ArrayList is a bit costly, which is on the order of n^2.

Let’s say I have a list of integers and I want to remove all the non-prime numbers from the list.

Typically, what we do is use iterator and a while loop to do that. We can’t iterate/remove at the same time with for each loops — we would end up with concurrent modification exceptions.

So...

Iterator<Integer> iterator = numbers.iterator();
        while (iterator.hasNext()) {
            Integer next = iterator.next();
            if (!isPrime(next)) {
                iterator.remove();
            }
        }

However, it has an order of n^2 complexity. We are doing two things here — iterating the entire list, which is n here. In the ArrayList, when you remove an element from an index, everything on the tail of the array has to be shoved up one space. That’s how the remove method works. It has to copy array data on each remove call. That means there are n copies. So it ends up being an order of n^2.

Java 8 has a removeIf method in the collection interface. For the ArrayList, it has an advanced implementation, which ends up being to the order of n.

numbers.removeIf(integer -> !isPrime(integer));

Here is the source code of the removeIf method from the Java 8 API:

    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        // figure out which elements are to be removed
        // any exception thrown from the filter predicate at this stage
        // will leave the collection unmodified
        int removeCount = 0;
        final BitSet removeSet = new BitSet(size);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if (filter.test(element)) {
                removeSet.set(i);
                removeCount++;
            }
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }

        // shift surviving elements left over the spaces left by removed elements
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            final int newSize = size - removeCount;
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:
concurrent ,arraylist ,java ,api

Published at DZone with permission of A. N. M. Bazlur Rahman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}