• 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 all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Bear Bibeault
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Junilu Lacar
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Jj Roberts
  • Tim Holloway
  • Piet Souris
Bartenders:
  • Himai Minh
  • Carey Brown
  • salvin francis

To extend or not to extend AbstractCollection

 
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
  • 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
  • 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
  • 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 ]
 
He was expelled for perverse baking experiments. This tiny ad is a model student:
Thread Boost feature
https://coderanch.com/t/674455/Thread-Boost-feature
reply
    Bookmark Topic Watch Topic
  • New Topic