• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

To extend or not to extend AbstractCollection

 
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've been bouncing back and forth with myself and different people with different opinions on this, so I ask the opinions of my fellow javaranchers to help me come to a conclusion.
I have a situation where I am retrieving records from a database that have a unique composite key. These records are then stored into a Map by the composite key and the object that represents the fields in the record (which also includes the composite key fields).
I implemented this as a collection by extending AbstractCollection and using the Map as the internal structure. The difference between this collection and any other collection though is that is works primarily by the composite key. For example:

coll.contains(obj) returns true is the composite key of obj is found in the Map
coll.remove(obj) removes the object from the collection where the composite key of obj is found in the Map.
I also added some other methods such as:
removeAllValue(Collection c) that removes all the objects from the collection where the objects in c are found by value in the Map (containsValue).

This works real well for set operations where I am comparing a collection from a flat file to what is already in the database. With these operations and the combination of cloneing I can do things like this:
process(Collection fileCollection, Collection dbCollection)
{
Collection updateCollection = fileCollection.clone();
updateCollection.retainAll(dbCollection);
updateCollection.removeAllValue(dbCollection);
update(updateCollection);

Collection insertCollection = fileCollection.clone();
insertCollection.removeAll(dbCollection);
insert(insertCollection);
Collection deleteCollection = dbCollection.clone();
deleteCollection.removeAll(fileCollection);
delete(deleteCollection);
}
This code essentially does 3 things:
1) Keep all the objects in the file collection that are contained (by compositekey) in the db collection, and remove all those where the objects are equal by value. This will leave only the objects in the collection that need updating in the database.
2) Remove all the objects in the file collection that are contained (by compositekey) in the db collection. This will leave only the objects in the collection that need inserting into the database.
3) Remove all the objects from the db collection that are contained (again by compositekey) in the file collection. This will leave only the objects in the collection that need to be deleted from the database.
This functionality seems so common that I'm surprised no one has come up with a common collection class or pattern that does this.

Has anyone else come up with, or has the need for, a hybrid Collection-backed-by-Map-using-keys solution?
Am I breaking all the rules for a Collection implementation by doing this (because the behavior of contains and other collection methods are different)?
Some have told me I should almost never implement or extend Collection or Map, but use the concrete versions available (HashSet, ArrayList, HashMap,etc) with helper classes. Others have said that I should create a collection type object but not implement or extend Collection and only implement the methods needed for the requirements.
I mainly am looking for any other similar examples or experiences so I can draw info from them.
Thanks,
John Brown
 
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What do you mean by a "composite key"?
Are you sure that you can't use the object itself as a Map key, by defining appropriate methods for equals() and hashCode() ?
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I gether the key uses a subset of the fields in the record, and in some contexts John needs equals() to compare only the key fields, while in others equals() must compare all fields. So the key must be represented by a separate class, with its own implementations of equals(), hashCode(), and maybe compareTo(), utilizing only the fields which are part of the key. This is what's usually meant by a composite key, I think.
John - the main thing I don't like about your new Collection class is the new methods are confusingly named. The normal contains() method of Collection compares values directly, while yours (of the same name) looks up keys first. I might call that containsByKey() instead for slightly greater clarity, to make clear this is not the standard contains(). I say containsByKey() rather than containsKey() because the latter would lead me to expect that the argument already is a key, which does not seem to be the case. Similar arguments for your remove(), removeAll(), retainAll() methods. These methods no longer do what the API of Collection says they do, so they should have different names.
I'm not sure I see any need for this new class. It seems you can use Maps to do everything you want already, without the need for a new wrapper:

The thing to remember is that any changes to the views returned by keySet() or values() also affect the whole Map.
In general it's certainly OK to create new implementations of the Collections interfaces, if the new implementations offer something new and useful. But bear in mind that it takes time to get these right, and other coders won't understand your new classes as readily. They're more likely to understand standard collections implementations. (And if they don't, it's more beneficial in the long term for them to spend time learning the standard implementations, rather than learning your implementation.)
[ August 15, 2002: Message edited by: Jim Yingst ]
 
Stop it! You're embarassing me! And you are embarrassing this tiny ad!
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic