7

We're taught that Java's ArrayList is less efficient for integers, because the list actually contains pointers, while an array of ints contains the integers in place, thus avoiding memory allocations and access.

My question is whether the JDK/JIT compiler optimizes this kind of inefficiency away? It has all the information to conclude these implementations are functionally equivalent , so it might as well replace ArrayList with an int[]-backed implementation under the hood.

1
  • @01 - totally agree on the 'premature-optimization' tag - this is just the theoretical discussion we all love to do sometime. Commented Jan 1, 2011 at 10:48

4 Answers 4

11

No, it can't, because you can store null in an ArrayList.

EDIT: Oh, and it also can't because generics are erased at compile time — at run time, the JRE can't distinguish ArrayLists by their element types. IOW, it's worse than just null — you can store any object in an ArrayList<Integer>.

Sign up to request clarification or add additional context in comments.

4 Comments

Theoretically, a future Java compiler/runtime might be able to get rid of the type casting, but the null issue is a permanent blocker for going all the way to int[]. Moreover, I know of quite a bit of code which stores nulls in arraylists, so it's not something that's likely to be able to vanish.
@Donal Fellows. null is always raise the problems in java. In this case it would be possible to use bit vector to store isNull property. So we can use one longer int[] to store all information from ArrayList<Integer>
The next problem would be turning Integer get(int) into int get(int) automagically to avoid autoboxing on every call!. (Killing most of the performance benefit I suspect)
@sign: Basically, by the time you're getting to that level of optimization, you're beyond the point where it's reasonable to expect JIT to reach, at least for the next few years.
3

No. http://jdevelopment.nl/java/java-best-practices-4-native-arrays-and-not-using-java-5/

1 Comment

But it's not (at first blush) inconceivable that Java could optimize for the particular case of an ArrayList of integers.
3

It could in theory but it doesn't. It may not be more efficient unless auto-boxing could be optimised out as well.

You can instead http://trove4j.sourceforge.net/javadocs/gnu/trove/TIntArrayList.html which wraps int[].

4 Comments

Yeah, I'm familiar with trove, this was more a theoretical question. +1 anyway.
@ripper234, I would have preferred them to support List<int> at least. Automatic detection would be ideal, but they haven't got basic escape analysis worked out yet. :P
But that wouldn't work because int isn't type-related to Object. While it would have been possible for the generic system to have been designed to support this sort of thing, it would have involved a much larger change to the classloader system than the language developers could stomach. After all, Java is deliberately less elaborate than C++.
@Donal, I can well understand them not wanting to automatically replace List<int> with a custom type. it could be done in theory but is best done at the moment by the developer. Perhaps compilers/jit will handle this sort of thing one day. It is possibly not worth the effort it takes (i.e. the improvement isn't that big for 90%+ of cases)
-4

So the implementation of such array can be like this

import java.util.AbstractList;
import java.util.List;
import java.util.RandomAccess;

public class IntArrayList extends AbstractList<Integer>
implements List<Integer> , RandomAccess /* todo , Cloneable, java.io.Serializable */{

    private static final int INT_SIZE_MINUS_ONE = 15;
    private static final int RIGHT_SHIFT = 4;

    private int size;
    private int isNull[];
    private int data[];

    IntArrayList(int size) {
        if (size < 0) {
            throw new RuntimeException("invalid size");
        }
        this.size = size;
        isNull = new int[(size + INT_SIZE_MINUS_ONE) >>> RIGHT_SHIFT];
        data = new int[size];
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
    }

    public Integer set(int index, Integer element) {
        rangeCheck(index);

        Integer oldValue = get(index);
        if (element == null) {
            isNull[index >>> RIGHT_SHIFT] &= ~(1 << (index & INT_SIZE_MINUS_ONE));
        } else {
            isNull[index >>> RIGHT_SHIFT] |= (1 << (index & INT_SIZE_MINUS_ONE));
            data[index] = element;
        }
        return oldValue;
    }

    @Override
    public Integer get(int index) {
        rangeCheck(index);
        if ((isNull[index >>> RIGHT_SHIFT] & (1 << (index & INT_SIZE_MINUS_ONE))) == 0) {
            return null;
        }
        return new Integer(data[index]);
    }

    @Override
    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }
}

It can be used anywhere as List<Integer>

Such kind of object can be useful for long term storage of information that rarely used. It will decrease fragmentation of heap at a cost of increased garbage generation on access to elements.

2 Comments

Really why downvote? If my answer is completely incorrect, please, give me a point.
Because it's not an answer to my question. I know how to implement an efficient IntArray.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.