views:

179

answers:

4

Note that I'm not actually doing anything with a database here, so ORM tools are probably not what I'm looking for.

I want to have some containers that each hold a number of objects, with all objects in one container being of the same class. The container should show some of the behaviour of a database table, namely:

  • allow one of the object's fields to be used as a unique key, i. e. other objects that have the same value in that field are not added to the container.
  • upon accepting a new object, the container should issue a numeric id that is returned to the caller of the insertion method.

Instead of throwing an error when a "duplicate entry" is being requested, the container should just skip insertion and return the key of the already existing object.

Now, I would write a generic container class that accepts objects which implement an interface to get the value of the key field and use a HashMap keyed with those values as the actual storage class. Is there a better approach using existing built-in classes? I was looking through HashSet and the like, but they didn't seem to fit.

+4  A: 

None of the Collections classes will do what you need. You'll have to write your own!

P.S. You'll also need to decide whether your class will be thread-safe or not.

P.P.S. ConcurrentHashMap is close, but not exactly the same. If you can subclass or wrap it or wrap the objects that enter your map such that you're relying only on that class for thread-safety, you'll have an efficient and thread-safe implementation.

Jason Cohen
+1  A: 

I was thinking you could do it with ArrayList, using the current location in the array as the "id", but that doesn't prevent you from making an insert at an existing location, plus when you insert at that location, it will move everything up. But you might base your own class on ArrayList, returning the current value of .size() after a .add.

Paul Tomblin
+3  A: 

You can simulate this behavior with a HashSet. If the objects you're adding to the collection have a field that you can use as a unique ID, just have that field returned by the object's hashCode() method (or use a calculated hash code value, either way should work).

HashSet won't throw an error when you add a duplicate entry, it just returns false. You could wrap (or extend) HashSet so that your add method returns the unique ID that you want as a return value.

Bill the Lizard
+1  A: 

Is there a reason why the object's hash code couldn't be used as a "numeric id"?

If not, then all you'd need to do is wrap the call into a ConcurrentHashMap, return the object's hashCode and use the putIfAbsent(K key, V value) method to ensure you don't add duplicates.

putIfAbsent also returns the existing value, so you could get its hashCode to return to your user.

See ConcurrentHashMap

Benjamin Borden
@Benjamin: hash codes can't be used as numeric ids because they're not unique.
CPerkins