The basic positional access operations (get
, set
, add
and remove
) behave just like their longer-named counterparts in Vector
(elementAt
, setElementAt
, insertElementAt
and removeElementAt
) with one noteworthy exception. The set
and remove
operations return the old value that is being overwritten or removed; the Vector
counterparts (setElementAt
and removeElementAt
) return nothing (void
). The search operations indexOf
and lastIndexOf
behave exactly like the identically named operations in Vector
.
The addAll
operation inserts all of the elements of the specified Collection
starting at the specified position. The elements are inserted in the order they are returned by the specified Collection
's iterator
. This call is the positional access analogue of Collection
's addAll
operation.
Here's a little function to swap two indexed values in a List
.
private static void swap(List a, int i, int j) {
Object tmp = a.get(i);
a.set(i, a.get(j));
a.set(j, tmp);
}
Of course there's one big difference. This is a polymorphic algorithm: it swaps two elements in any List
, regardless of its implementation type. "Big deal," you say, "What's it good for?" Funny you should ask. Take a look at this:
public static void shuffle(List list, Random rnd) {
for (int i=list.size(); i>1; i--)
swap(list, i-1, rnd.nextInt(i));
}
This algorithm (which is included in the JDK's Collections
class) randomly permutes the specified List
using the specified source of randomness. It's a bit subtle: It runs up the list from the bottom, repeatedly swapping a randomly selected element into the current position. Unlike most naive attempts at shuffling, it's fair (all permutations occur with equal likelihood, assuming an unbiased source of randomness) and fast (requiring exactly list.size()-1
iterations). The following short program uses this algorithm to print the words in its argument list in random order:
import java.util.*;
public class Shuffle {
public static void main(String args[]) {
List l = new ArrayList();
for (int i=0; i<args.length; i++)
l.add(args[i]);
Collections.shuffle(l, new Random());
System.out.println(l);
}
}
In fact, we can make this program even shorter and faster. The Arrays
class has a static factory method called asList
that allows an array to be viewed as a List
. This method does not copy the array; changes in the List
write through to the array, and vice-versa. The resulting List
is not a general-purpose List
implementation, in that it doesn't implement the (optional) add
and remove
operations: arrays are not resizable. Taking advantage of Arrays.asList
and calling an alternate form of shuffle
that uses a default source of randomness, you get the following tiny program, whose behavior is identical to the previous program:
import java.util.*;
public class Shuffle {
public static void main(String args[]) {
List l = Arrays.asList(args);
Collections.shuffle(l);
System.out.println(l);
}
}
No comments:
Post a Comment