Collections
Collections in Java involve several inconsistencies which seem quite odd for a C# developer. To understand some of the oddities of Java collections, you should keep in mind that Java is an old framework and at some points in its evolution, some new paradigms have been introduced and some old paradigms have been changed.
Before Java 5, you had collections that had Object
as contained type. Later Java versions have generic collections and generic collection-interfaces. I’ll talk only about the generics here, but am leaving away the
Collection Interfaces
Modern Java collection handling is based completely on generic interfaces. The basic interface for collections is Collection
.
From Collection
derived interfaces are
List, Set, Queue, Deque, SortedSet, NavigableSet
and the thread-safe interfaces concurrent.BlockingQueue, concurrent.BlockingDeque, concurrent.TransferQueue
.
The following table shows the interfaces and the implementations available in Java SE 7. The names are mostly self-explanatory but where needed, some explanations are given under the table.
Interface | Implementing Class | C# Analogon |
---|---|---|
Collection |
All of the following | ICollection |
List |
LinkedList, ArrayList, Vector, Stack |
IList |
Set |
HashSet, TreeSet, LinkedHashSet |
ISet |
Queue |
ArrayDeque, LinkedList |
Queue class |
Deque |
ArrayDeque, LinkedList |
LinkedList class |
ArrayList
andVector
are nearly the same, the main difference is thatVector
is synchronized andArrayList
is not.Stack
extendsVector
and so is synchronized, too.LinkedHashSet
is implemented as a hash table with an added linked list. The linked list orders its elements in the order the elements have been added to theLinkedHashSet
.
Map Interface
The Map
interface is equivalent to C#’s IDictionary
. Map
is the base interface of these extended interfaces: SortedMap, NavigableMap, concurrent.ConcurrentMap
and concurrent.ConcurrentNavigableMap
.
Gotcha: Strange, but true: a Map
is not a Collection
in Java.
HashMap, Hashtable, TreeMap, WeakHashMap, Properties
and LinkedHashMap
are the most important implementations of the Map
interface.
- The difference between
Hashtable
andHashMap
is:Hashtable
is synchronized,HashMap
is not. - A
TreeMap
is implemented as tree. It is ordered by key. LinkedHashMap
keeps a linked list which is ordered by the order of insertion of elements into the list.- A
WeakHashMap
stores keys as weak references. The C# analogon to aWeakHashMap
is aDictionary
.>
Gotcha: TheWeakHashMap
automatically removes an entry if the entry’s key is garbage collected. Of course, aDictionary
does not remove entries automatically.> Properties
can be used for ini-files.
Map Example
Map h = new HashMap();
h.put(20097, "Hamburg");
h.put(76307, "Karlsbad-Auerbach");
h.put(76307, "Karlsbad");
if (h.containsKey(20097))
System.out.println(h.get(20097)); // Hamburg
System.out.println(h.get(22222)); // null
System.out.println(h.get(76307)); // Karlsbad
Set keys = h.keySet();
// -> { 20097, 76307 } in unpredictable order.
Collection values = h.values();
// -> { "Hamburg", "Karlsbad" } in unpredictable order.
Set> entries = h.entrySet();
// -> { {20097, "Hamburg"}, {76307, "Karlsbad"} }
// in unpredictable order.
Properties class
The Properties
class is a Map that according to docs shall only contain String-String
pairs. Nevertheless, and strange but true: it is derived from Hashtable
, not from Hashtable
.
The Properties
class can be used to store ini-like files on disk. An example on how to use Properties
to read and write data follows.
Properties p = new Properties();
p.setProperty("a", "A");
p.setProperty("b", "xy");
static void StoreProperties(String filename, Properties prop)
throws IOException
{
FileWriter fw = null;
try
{
fw = new FileWriter(filename);
prop.store(fw, "This is a comment.");
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (fw != null)
fw.close(); // may throw
}
}
static void ReadProperties(String filename, Properties prop)
throws IOException
{
prop.clear();
Reader fr = null;
try
{
fr = new FileReader(filename);
prop.load(fr);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if( fr != null)
fr.close(); // may throw
}
}
Dictionary
From Java 1.0 on, there has been the abstract class Dictionary
which of course denotes the same concept as the Map
. So you will find this in legacy code frequently. Nowadays, Dictionary
is deprecated.
IEnumerable, Equals, Indexers, …
equals, hashCode and compareTo
The Java methods equals, hashCode
and compareTo
are analog to C#’s Equals, GetHashCode
and CompareTo
. Like in C#, if you use any of the generic containers you must be aware that these methods must be implemented on your classes. Otherwise strange things will happen.
IEnumerable, IEnumerator / Iterable, Iterator
Iterable
is the Java equivalent of C#’s IEnumerable
and Iterator
is the Java equivalent of IEnumerator
. The following two code snippets show their usage.
// Java
TreeSet ts = ...;
Iterable t = ts;
for(java.util.Iterator it = t.iterator(); it.hasNext();)
System.out.print(it.next() + " ");
// C#
List a = ...;
IEnumerable t = a;
for(IEnumerator en = t.GetEnumerator(); en.MoveNext();)
Console.Write(en.Current + " ");
Some further Gotchas:
- Ordinary Java arrays do not implement
IEnumerable
. Nevertheless you can iterate over them by the extended for loop. - Collections of primitive types are not allowed in Java. You need to use the corresponding wrapper class. Example:
List
= new LinkedList (); - Indexers do not exist in Java. Access to elements of array-like collections can be done by
get(i)
instead.