views:

1094

answers:

3
private HashMap<DataObject, HashSet> AllDataObjects;

...

/** Returns all DataObject elements that are NOT in the specified set. */
private DataObject[] invert( HashSet<DataObject> set )
{
    HashSet<DataObject> keys = (HashSet) AllDataObjects.keySet();
    keys = (HashSet) keys.clone();

    keys.removeAll( set );

    return (DataObject[]) keys.toArray();
}

Note that I don't want to alter AllDataObjects through this process. I casted the set of AllDataObjects' keys (which are the DataObjects I want the set parameter to subtract from) into a HashSet to use clone, which supposedly returns a shallow copy that I can then remove set from without affecting AllDataObjects.

Does this look right to you?

+4  A: 

Create a new set and give the one to be cloned as an argument. This avoids casting and so you don't lose generics.

private DataObject[] invert( Set<DataObject> set ){
    Set<DataObject> keys = new HashSet<DataObject>(AllDataObjects.keySet());
    keys.removeAll( set );
    return keys.toArray(new DataObject[]{});
}

It's also worth noting that you should use Set rather than HashSet for the parameter so as to not overly burden your clients.

iny
In fact arguably you should declare the argument to be Collection<? extends DataObject>, both so they can pass in a List if they have one handy (as this will still work), and so they can pass in a collection of some kind of subclass without having to wrap it.
Andrzej Doyle
+1  A: 

Knowing that these sets were populated by a relational query, I would suggest that you at least trade off writing a better SQL query to get what you want rather than doing it in memory. There are several reasons why. First, most relational databases are optimized to do this more efficiently than your code will. Second, you're letting the server where the relational database is running do more of the work that it was intended for. Third, if the size of the sets become large you'll be unnecessarily burdening the middle tier by having to bring back the results, allocate memory for them, and then throw away the unwanted results.

duffymo
I'm not using a database yet, but I plan too soon. There's a few parts to the basic design I haven't ironed out yet, which I'd prefer to do with ordinary code for now.
Daddy Warbox
A: 

I think this link has a better way to write that method if you must:

http://stackoverflow.com/questions/393968/java-is-there-an-easy-quick-way-to-and-or-or-xor-together-sets

duffymo