Why not implement a List backed Map? It's easy and is something every developer should have in their toolbox IMO. I believe commons collections has something along these lines too, though I don't tend to use it.
Code:
/*
* MPSC-Util - A library of miscellaneous common code
* Copyright (C) 2005 Matt Parker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package uk.co.mpcontracting.modules.util;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* An implementation of a <code>Map</code> that is backed by a <code>java.util.ArrayList</code>
*
* @author Matt Parker (matt@mpcontracting.co.uk)
*/
public class OrderedSet extends AbstractSet implements Serializable
{
private List list;
/**
* Constructs an empty <code>OrderedSet</code>
*/
public OrderedSet()
{
super();
list = new ArrayList();
}
/**
* Constructs an empty <code>OrderedSet</code> with the specified initial capacity
*
* @param initialCapacity The initial capacity
*/
public OrderedSet(int initialCapacity)
{
super();
list = new ArrayList(initialCapacity);
}
/**
* Constructs a new <code>OrderedSet</code> containing the elements in the specified collection
*
* @param collection The specified collection
*/
public OrderedSet(Collection collection)
{
super();
list = new ArrayList(collection);
}
/**
* Returns an iterator over the elements in this set
*
* @return An iterator over the elements in this set
*/
public Iterator iterator()
{
return (list.iterator());
}
/**
* Returns the number of elements in this set
*
* @return The number of elements in this set
*/
public int size()
{
return (list.size());
}
/**
* Adds the specified object to this set if it isn't already present
*
* @param object The object to add to this set
* @return Whether the set already contained the specified object
*/
public boolean add(Object object)
{
if (!contains(object))
{
return (list.add(object));
}
else
{
return (false);
}
}
/**
* Retrieves the value stored at a given index. This is possible because the set
* is backed with a <code>java.util.ArrayList</code>
*
* @param index The given index
* @return The value stored at the given index
*/
public Object get(int index)
{
return (list.get(index));
}
}
Code:
/*
* MPSC-Util - A library of miscellaneous common code
* Copyright (C) 2005 Matt Parker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package uk.co.mpcontracting.modules.util;
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* An implementation of a <code>Map</code> that is backed by an <code>OrderedSet</code>
*
* @author Matt Parker (matt@mpcontracting.co.uk)
*/
public class OrderedMap extends AbstractMap implements Serializable
{
private Set entrySet;
/**
* Constructs an empty <code>OrderedMap</code>
*/
public OrderedMap()
{
super();
entrySet = new OrderedSet();
}
/**
* Constructs an empty <code>OrderedMap</code> with the specified initial capacity
*
* @param initialCapacity The initial capacity
*/
public OrderedMap(int initialCapacity)
{
super();
entrySet = new OrderedSet(initialCapacity);
}
/**
* Constructs a new <code>OrderedMap</code> with the same mappings as the specified map
*
* @param map The specified map
*/
public OrderedMap(Map map)
{
this();
putAll(map);
}
/**
* Retrieves a collection of the entries stored in this map
*
* @return A collection of the entries stored in this map
*/
public Set entrySet()
{
return (entrySet);
}
/**
* Associates the given value with the specified key in this map. If the
* map previously contained a mapping for this key, the old value is
* replaced
*
* @param key The specified key
* @param value The given value
* @return The value previously associated with the specified key, or <code>null</code>
* if there was no mapping for the key
*/
public Object put(Object key, Object value)
{
Object previousValue = null;
Entry existingEntry = null;
for (Iterator iterator = entrySet.iterator(); iterator.hasNext();)
{
existingEntry = (Entry)iterator.next();
if ((key == null) && (existingEntry.getKey() == null))
{
previousValue = existingEntry.getValue();
break;
}
else if ((key != null) && (key.equals(existingEntry.getKey())))
{
previousValue = existingEntry.getValue();
break;
}
}
if (previousValue != null)
{
existingEntry.setValue(value);
return (previousValue);
}
else
{
entrySet.add(new SimpleEntry(key, value));
return (null);
}
}
/**
* Retrieves the value stored at a given index. This is possible because the map
* is backed with an <code>OrderedSet</code>
*
* @param index The given index
* @return The value stored at the given index
*/
public Object get(int index)
{
Entry entry = (Entry)((OrderedSet)entrySet).get(index);
return (entry.getValue());
}
/**
* A simple implementation of the <code>Entry</code> interface
*/
private class SimpleEntry implements Entry, Serializable
{
Object key;
Object value;
public SimpleEntry(Object key, Object value)
{
this.key = key;
this.value = value;
}
public SimpleEntry(Map.Entry entry)
{
key = entry.getKey();
value = entry.getValue();
}
public Object getKey()
{
return (key);
}
public Object getValue()
{
return (value);
}
public Object setValue(Object value)
{
Object oldValue = this.value;
this.value = value;
return (oldValue);
}
public boolean equals(Object object)
{
if (!(object instanceof Map.Entry))
{
return (false);
}
Map.Entry entry = (Map.Entry)object;
return (eq(key, entry.getKey()) && eq(value, entry.getValue()));
}
public int hashCode()
{
return (((key == null) ? 0 : key.hashCode()) ^
((value == null) ? 0 : value.hashCode()));
}
public String toString()
{
return (key + "=" + value);
}
private boolean eq(Object object1, Object object2)
{
return ((object1 == null) ? (object2 == null) : object1.equals(object2));
}
}
}