to manipulate the data. Java technology has always offered support for collections, for example via the
Vector and Hashtable classes, but in JDK 1.2, a new framework for collections has been defined and
implemented. The old classes can still be used, but the new preferred approach has significant
advantages.
Before getting into a lot of the details of how collections work, it's
worth looking at a simple example:
import java.util.*;
5 * 5 = 25
and displays it.
Collection Frameworks
import java.util.*;
return s1.toLowerCase(
).compareTo(s2.toLowerCase());
}
list.add("abc");
list.add("DEF");
list.add("ghi");
// standard sort
Collections.sort(list);
Iterator iter = list.iterator();
while (iter.hasNext())
System.out.println(iter.next());
Types of Interfaces
The Collection interface itself does not enforce any policy, such as
no duplicates or ordering. Such policies are enforced by
subinterfaces. Also, it's possible to define your own subinterface if
you have need to establish a different set of policies. Note that Map is
at the root of a distinct interface hierarchy; a map is not really a
collection of elements, but a mapping of keys to values.
and maps have functionality to get a list of all the keys contained in
the map object.
import java.util.*;
Note that each entry in the map contains two values; one for the key
and the other for the value. A map cannot contain any duplicates, and
no ordering is imposed. When this program is run, output is like:
Larry 234-5678
Felicia 345-6789
Mary 456-7890
with the first value for "Mary" overwritten, and with the iterator
retrieval order different from the order in which the elements were
added to the map.
import java.util.*;
3
2
1
Algorithms
import java.util.*;
import java.util.*;
list.add("abc");
list.add("def");
list.add("ghi");
list.add("jkl");
Collections.shuffle(list);
If you want to exercise finer control over the shuffling process, you
can also specify a Random object.
import java.util.*;
Collections.reverse(list);
import java.util.*;
System.out.println("max = "
+ Collections.max(hs));
}
}
import java.util.*;
Comparing Objects
import java.util.*;
class test {
private int x;
public test(int i) {x = i;}
}
and you run it. What happens? This example gives an exception,
caused by failure to specify any means of comparing instances of the
test class. Such comparisons are done when sorting, and there's no
automatic way to order objects.
One way of ordering is illustrated in the sort example above, using
the Comparator interface. Another approach is to use the
Comparable interface, for example:
import java.util.*;
dummy.compare(obj1, obj2)
obj1.compareTo(obj2)
Iterators
import java.util.*;
But there is a way to avoid this failure, and that is to effect the
modification via the iterator itself, as the example illustrates. That is,
add is called on the iterator instead of on the list that the iterator is
traversing. This allows the modification to be done in an orderly way.
import java.util.*;
ListIterator iter =
list.listIterator(list.size());
while (iter.hasPrevious())
System.out.println(iter.previous());
}
}
Output is:
ghi
def
abc
Serialization
try {
FileOutputStream fos =
new FileOutputStream("test.ser");
ObjectOutputStream oos =
new ObjectOutputStream(fos);
oos.writeObject(hm);
oos.close();
}
catch (Throwable e) {
System.err.println(e);
}
}
}
import java.io.*;
import java.util.*;
try {
FileInputStream fis =
new FileInputStream("test.ser");
ObjectInputStream ois =
new ObjectInputStream(fis);
hm = (Map)ois.readObject();
ois.close();
}
catch (Throwable e) {
System.err.println(e);
}
if (hm != null) {
Iterator iter = hm.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry e = (Map.Entry)iter.next();
System.out.println(e.getKey() + " "
+ e.getValue());
}
}
}
}
Exceptions
Properties of Collections
import java.util.*;
//list2.add("xyz");
list2.set(1, "xyz");
import java.util.*;
list = Collections.unmodifiableList(list);
list.add("xyz");
// triggers exception
}
}
In this example, the list has a wrapper put on it, and from then on is
not modifiable at all. A wrapper takes a collection and returns another
collection, one with particular properties imposed on it.
Collections.unmodifiableList is a wrapper implementation.
Synchronization
import java.util.*;
lst = Collections.synchronizedList(lst);
synchronized (lst) {
Iterator iter = lst.iterator();
while (iter.hasNext())
System.out.println(iter.next());
}
}
}
You may be convinced by now that collections are a good thing, but
what if you're trying to maintain a lot of old code that uses
Hashtable and Vector and Enumeration and so on, or that even
uses simple arrays to represent groupings of elements?
One answer to this question is to note that some of the old classes, for
example Vector, have been retrofitted to work with the collections
framework. Vector is now a subclass of AbstractList, and
implements List. It's still better to use ArrayList if you can, but
Vector will continue to work.
import java.util.*;
f1(new Vector(list1));
String slist[] =
(String[])list1.toArray(new String[0]);
for (int i = 0; i < slist.length; i++)
System.out.println(slist[i]);
Enumeration e =
Collections.enumeration(list1);
while (e.hasMoreElements())
System.out.println(e.nextElement());
String list2[] =
new String[]{"abc",
"def", "ghi"};
f2(Arrays.asList(list2));
}
}
You might also have an old legacy API, one that implements
collections in some totally different way. One solution to this issue is
to use an adapter class that implements one of the core collection
interfaces, and translates method calls found in that interface into
your old API methods. In other words, intercept and translate calls.
Programming Tips and API Design
is preferable to:
For method return types, it's acceptable and even desirable to use
specific implementation types. For example, ArrayList has very
different performance characteristics than LinkedList, and because
of this, the user of a method needs to know just what type of data
structure is being returned. The return type can always be converted
to a more general type, for example:
void g()
{
List lst = f();
}
Performance
HashSet is much faster than TreeSet (constant vs. log(N)), but does
not offer any guarantees on ordering, and similarly for HashMap and
TreeMap.
Customization
The first of these is beyond the scope of this paper. However, the
second can be illustrated by a simple example, one that enforces a
policy such that only String objects can be added to an ArrayList:
import java.util.*;
import java.util.*;
/*
Implements List via a run-length encoding data
structure. The structure is divided into slots,
each slot representing one or more contiguous
elements that are equivalent, using equals() for
comparison.
currmax += n;
}
// binary search
// default constructor
public RunArrayList()
{
sublist = new int[10];
objlist = new Object[10];
currmax = -1;
}
return objlist[findslot(index)];
}
if (index == sz) {
if (sz > 0 &&
equals(objlist[currmax], element)) {
sublist[currmax]++;
}
else {
if (currmax + 1 == sublist.length)
growlist();
currmax++;
sublist[currmax] = sz;
objlist[currmax] = element;
}
}
else {
int slot = findslot(index);
int startincr = slot;
if (!equals(objlist[slot], element)) {
if (index == slotlo(slot)) {
makeslot(slot, 1);
sublist[slot + 1] =
sublist[slot];
sublist[slot] = index;
objlist[slot + 1] =
objlist[slot];
objlist[slot] = element;
startincr++;
}
else {
makeslot(slot, 2);
sublist[slot + 2] =
sublist[slot];
sublist[slot + 1] = index;
sublist[slot] = index - 1;
objlist[slot + 2] =
objlist[slot];
objlist[slot + 1] = element;
startincr += 2;
}
}
// remove an element
public Object remove(int index)
{
if (index < 0 || index >= size())
throw new IndexOutOfBoundsException();
if (slotlo(slot) == slothi(slot)) {
if (slot < currmax) {
System.arraycopy(sublist, slot + 1,
sublist, slot, currmax - slot);
System.arraycopy(objlist, slot + 1,
objlist, slot, currmax - slot);
}
objlist[currmax--] = null;
}
// decrement indices
return obj;
}
}
boolean add =
(sz <= LISTSZ &&
rand(1, 3) >= 2
|| sz > LISTSZ &&
rand(1, 3) < 2);
// do a random get()
if (sz > 0) {
int pos = rand(0, sz - 1);
Object o1 = al.get(pos);
Object o2 = rl.get(pos);
boolean b = (o1 == null ?
(o2 == null) : o1.equals(o2));
if (!b) {
System.out.println("get");
break;
}
}
// add
if (add) {
int choice = rand(1, 3);
if (choice == 1) {
rl.add(obj);
al.add(obj);
}
else if (choice == 2) {
int pos = rand(0, sz);
rl.add(pos, obj);
al.add(pos, obj);
}
else if (sz > 0) {
int pos = rand(0, sz - 1);
rl.set(pos, obj);
al.set(pos, obj);
}
}
// remove
More Information
Oracle is reviewing the Sun product roadmap and will provide guidance to customers in
accordance with Oracle's standard product communication policies. Any resulting features and
timing of release of such features as determined by Oracle's review of roadmaps, are at the sole
discretion of Oracle. All product roadmap information, whether communicated by Sun
Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or
functionality, and should not be relied upon in making purchasing decisions. It is intended for
information purposes only, and may not be incorporated into any contract.
About Sun | About This Site | Newsletters | Contact Us |
Employment | How to Buy | Licensing | Terms of Use |
Privacy | Trademarks
© 2010, Oracle Corporation and/or its affiliates