Times shown are the average of three runs, and all times have been normalized
to the first table cell; i.e., the time taken by the ArrayList to iterate the list using the List.get() method, using java -client.

Table 1: Access times for loop types and access methods

Loop type (loop test) and access method

ArrayList
java -client

LinkedList
java -client

ArrayList
java -server

LinkedList
java -server

loop counter (i<n) and list.get()

100%

too long

77.5%

too long

iterator (Iterator.hasNext()) and Iterator.next()

141%

219%

109%

213%

iterator (i<n) and iterator.next()

121%

205%

98%

193%

RandomAccess test with loop from row 1 or 3

100%

205%

77.5%

193%

Note that HotSpot is capable of optimizing away accesses that are
unnecessary, so the test accessed and operated on the list elements in a way
that could not eliminate the list element access. The test code is available here.

The most important results are in the last two rows of the table. The last row shows the
times obtained by making full use of the RandomAccess interface;
the row before that shows the most optimal general technique for iterating
lists, if RandomAccess were not available. The size of the lists I
used for the test (and consequently, the number of loop iterations required to
access every element) was sufficiently large that the instanceof
test had no measurable cost in comparison to the time taken to run the loop.
Consequently, we can see that that there was no cost (but also no benefit) in
adding the instanceofRandomAccess test when iterating
the LinkedList; whereas the ArrayList was iterated
more than 20% quicker when the instanceof test was included.

Forward and backward compatibility

What should you do if you are implementing code now? Obviously, you can start
developing with a 1.4 (beta) release, but this is not an option everywhere.
There are three aspects to using RandomAccess if you are developing
code now:

You may want to include code referencing
RandomAccess without moving to 1.4; many development environments
cannot be upgraded rapidly or to a beta release.

Many projects need their code to be able to run in any JVM, so
the code needs to be backwards-compatible to run in JVMs using releases
earlier than 1.4, where RandomAccess does not exist.

You will want to make your code forward-compatible so that it
will automatically take advantage of RandomAccess when running in
a 1.4+ JVM.

Making RandomAccess available to your development environment is
the first issue, and this can be as simple as adding the
RandomAccess interface to your classpath. Any version of the SDK
can create the RandomAccess interface. The definition for
RandomAccess is

package java.util;
public interface RandomAccess {}

This interface can be created using javac, as follows:

Create a directory called temp

In temp, create a directory called java

In java, create a directory called util

In util, create a file called RandomAccess.java, containing
the definition just given

Compile RandomAccess.java, using javac: javac
RandomAccess.java

Now including temp in your classpath should enable classes that refer
to RandomAccess to be compiled.

Some Java integrated development environments (IDEs) can make it difficult to
add a class to the core SDK packages. If this is the case for your IDE, your
only hope is that it accepts an external classpath for compilation purposes, in
which case the custom-generated RandomAccess class will need to be
held in that external classpath.

We also need to handle RandomAccess in the runtime environment.
For pre-1.4 environments, the test if (listObject instanceof
RandomAccess) will generate a NoClassDefFoundError at
runtime, when the JVM tries to load the RandomAccess class. For the
instanceof test to be evaluated, the class has to be loaded;
however, we can guard the test so that it is only executed if
RandomAccess is available. The simplest way to do this is to check
if RandomAccess exists, setting a boolean guard as the outcome of
that test:

Then, finally, we will need to change our instanceof tests to
use the RandomAccessExists variable as a guard:

if (RandomAccessExists && (listObject instanceof RandomAccess) )

Now we have the solution for all three aspects mentioned at the beginning of
this section:

The RandomAccess interface can be created and compiled easily
with any SDK, and this manually-compiled version can be used at compilation
time as a stand-in, to compile any code which refers to
RandomAccess.

The guarded instanceof test will automatically revert to the
Iterator loop if RandomAccess does not exist, and should avoid
throwing a NoClassDefFoundError in pre-1.4 JVMs.

The guarded instanceof test will also automatically use
the faster loop branch when RandomAccess does exist and the list
object implements it.