Re: Collection of distinc objects
Dzejm wrote:
Ok. It was simple. Sorry for bothering. It should work I think:
[...]
Also look into java.util.IdentityHashMap,
Although, I don't know why Java doesn't provode IdentityHashSet, ohwell.
Thanks. That's better solution than mine. My code returns always "1" for
distinct objects with the same hashCode. So it would tell that (a > b) and
(b > a) at the same time. Probably it would not work.
I wonder if it is possible to implement in java any comparison function that
impose some kind of constant order for objects with the same hashCode. I
mean function with always returns
-1 for foo(a,b) and 1 for foo(b,a) when (a != b). Probably it is totally
impossible. Isn't it ?
For your original problem, I'd use a HashSet and objects in it that
don't override Object.hashCode(). If the objects do override hashCode()
and that can't be readily changed I'd put them in a holder -- in fact,
I'd create something like
package whatever.util;
public final class Holder<T> {
public T object;
}
Then you can use a HashSet<Holder<Foo>> to collect Foos without
discarding duplicates (as decided by Foo's equality operator and hash
code method) unless they are actually the same instance.
Well, as long as you can code it so you can't end up with two different
Holders referencing the same Foo. Or you can stuff Foos in an
IdentityHashMap as keys with null values, and use the keySet() method to
get a Set view of the Foos.
As for imposing an arbitrary but fixed order on instances of a class,
you can use something like:
public interface Numbered {
public long getInstanceNumber ();
}
public class AbstractNumbered implements Numbered {
private static long nextInstance = 0;
private long instanceNumber;
public AbstractNumbered () {
instanceNumber = nextInstance;
++nextInstance;
}
public long getInstanceNumber () {
return instanceNumber;
}
}
public class Foo extends AbstractNumbered {
public Foo (args) {
construct stuff
}
public Foo (otherArgs) {
construct stuff
}
other stuff
}
public class InstanceNumberComparator<T extends Numbered> implements
Comparator<Foo> {
public int compare (T foo1, T foo2) {
long n1 = foo1.getInstanceNumber();
long n2 = foo2.getInstanceNumber();
return (n1 < n2)?-1:((n1 > n2)?1:0);
}
}
Now you can use Numbereds in things like TreeSet using an
InstanceNumberComparator. You can extend AbstractNumbered and not even
have to worry about implementing the numbering. (Everything extending
AbstractNumbered ends up numbered from a single sequence, mind you, so
if you have Foos and Bars both derived from AbstractNumbered you might
have Foos with numbers 1 and 2, a Bar with number 3, a Foo numbered 4,
etc.; this has no downside and does have the benefit that not only does
every Foo have a unique number, but this is true even if Foo has a bunch
of subclasses and you get all this for free. Also it won't run out of
unique numbers and "wrap" before you have OOME on any
presently-conceivable deployment system, unless you create and discard
truly stupendous numbers of objects descended from AbstractNumbered over
time on a rock-solid system with a rock-solid power supply. This
probably means a Linux box on a UPS running for decades doing nothing
*but* create objects without maintaining references to any of them. It
certainly won't run out on a normal system before either the power fails
for whatever reason or Windows needs rebooting again.)