Yes it is possible to do such a thing. But it won't allow you to put your objects into a HashMap, HashSet, etc. That's because the standard collection classes expect key objects to provide the equals and hashCode methods.(That's the way they are designed to work ...).
Yes it is possible to do such a thing. But it won't allow you to put your objects into a HashMap, HashSet, etc. That's because the standard collection classes expect key objects to provide the equals and hashCode methods.(That's the way they are designed to work ...) Alternatives: Implement a wrapper class that holds an instance of the real class, and provides its own implementation of equals and hashCode. Implement your own hashtable-based classes which can use a "hashable" object to provide equals and hashcode functionality.
Bite the bullet and implement equals and hashCode overrides on the relevant classes. In fact, the 3rd option is probably the best, because your codebase most likely needs to to be using a consistent notion of what it means for these objects to be equal. There are other things that suggest that your code needs an overhaul.
For instance, the fact that it is currently using an array of objects instead of a Set implementation to represent what is apparently supposed to be a set. On the other hand, maybe there was/is some real (or imagined) performance reason for the current implementation; e.g. Reduction of memory usage. In that case, you should probably write a bunch of helper methods for doing operations like concatenating 2 sets represented as arrays.
90% of the time when a user wants an equivalence relation there is already a more straightforward solution. You want to de-duplicate a bunch of things based on ids only? Can you just put them all into a Map with the ids as keys, then get the values() collection of that?
Very interesting solution – gasan Mar 9 at 11:55 that doesn't work if you want to pick which properties of the key define equality/hashing and you want to put something else as the value. Your solution only works if the important property of some key is singular, it doesn't work if you want to pick 2+ but not all important properties used by the key in its hashing/equals. – mP.
Mar 28 at 10:00 if someone writes one up is Guice interested? – mP. Mar 28 at 10:01.
Of course you can create some external object providing an equality comparison and a HashCode. But the build-in collections of Java do not use such an object for their comparisons/lookup. I once did create an interface like this in my package-collection (just freshly translated to english): public interface HashableEquivalenceRelation { /** * Returns true if two objects are considered equal.
* * This should form an equivalence relation, meaning it * should fulfill these properties: * * Reflexivity: {@code areEqual(o, o)} * should always return true. * Symmetry: {@code areEqual(o1,o2) == areEqual(o2,o1)} * for all objects o1 and o2 * Transitivity: If {@code areEqual(o1, o2)} and {@code areEqual(o2,o3)}, * then {@code areEqual(o1,o3}} should hold too. * * Additionally, the relation should be temporary consistent, i.e.
The * result of this method for the same two objects should not change as * long as the objects do not change significantly (the precise meaning of * change significantly is dependent on the implementation). * * Also, if {@code areEqual(o1, o2)} holds true, then {@code hashCode(o1) == hashCode(o2)} * must be true too. */ public boolean areEqual(Object o1, Object o2); /** * Returns a hashCode for an arbitrary object.
* * This should be temporary consistent, i.e. The result for the same * objects should not change as long as the object does not change significantly * (with change significantly having the same meaning as for {@link areEqual}). * * Also, if {@code areEqual(o1, o2)} holds true, then {@code hashCode(o1) == hashCode(o2)} * must be true too.
*/ public int hashCode(Object o); } Than I had a group of interfaces CustomCollection, CustomSet, CustomList, CustomMap, etc. Defined like the interfaces in java. Util, but using such an equivalence relation for all the methods instead of the build-in relation given by Object.equals. I had some default implementations, too: /** * The equivalence relation induced by Object#equals.
*/ public final static EquivalenceRelation DEFAULT = new EquivalenceRelation() { public boolean areEqual(Object o1, Object o2) { return o1 == o2 || o1! = null && o1. Equals(o2); } public int hashCode(Object ob) { return ob == null?
0 : ob.hashCode(); } public String toString() { return ""; } }; /** * The equivalence relation induced by {@code ==}. * (The hashCode used is {@link System#identityHashCode}.) */ public final static EquivalenceRelation IDENTITY = new EquivalenceRelation() { public boolean areEqual(Object o1, Object o2) { return o1 == o2; } public int hashCode(Object ob) { return System. IdentityHashCode(ob); } public String toString() { return ""; } }; /** * The all-relation: every object is equivalent to every other one.
*/ public final static EquivalenceRelation ALL = new EquivalenceRelation() { public boolean areEqual(Object o1, Object o2) { return true; } public int hashCode(Object ob) { return 0; } public String toString() { return ""; } }; /** * An equivalence relation partitioning the references * in two groups: the null reference and any other reference. */ public final static EquivalenceRelation NULL_OR_NOT_NULL = new EquivalenceRelation() { public boolean areEqual(Object o1, Object o2) { return (o1 == null && o2 == null) || (o1! = null && o2!
= null); } public int hashCode(Object o) { return o == null?0 : 1; } public String toString() { return ""; } }; /** * Two objects are equivalent if they are of the same (actual) class. */ public final static EquivalenceRelation SAME_CLASS = new EquivalenceRelation() { public boolean areEqual(Object o1, Object o2) { return o1 == o2 || o1! = null && o2!
= null && o1.getClass() == o2.getClass(); } public int hashCode(Object o) { return o == null?0 : o.getClass().hashCode(); } public String toString() { return ""; } }; /** * Compares strings ignoring case. * Other objects give a {@link ClassCastException}. */ public final static EquivalenceRelation STRINGS_IGNORE_CASE = new EquivalenceRelation() { public boolean areEqual(Object o1, Object o2) { return o1 == null?
O2 == null : ((String)o1). EqualsIgnoreCase((String)o2); } public int hashCode(Object o) { return o == null? -12345 : ((String)o).toUpperCase().hashCode(); } public String toString() { return ""; } }; /** * Compares {@link CharSequence} implementations by content.
* Other object give a {@link ClassCastException}. */ public final static EquivalenceRelation CHAR_SEQUENCE_CONTENT = new EquivalenceRelation() { public boolean areEqual(Object o1, Object o2) { CharSequence seq1 = (CharSequence)o1; CharSequence seq2 = (CharSequence)o2; if (seq1 == null ^ seq2 == null) // nur eins von beiden null return false; if (seq1 == seq2) // umfasst auch den Fall null == null return true; int size = seq1.length(); if (seq2.length()! = size) return false; for (int I = 0; I = seq2.
CharAt(i)) return false; } return true; } /** * Entrspricht String. HashCode */ public int hashCode(Object o) { CharSequence sequence = (CharSequence)o; if (sequence == null) return 0; int hash = 0; int size = sequence.length(); for (int I = 0; I CharAt(i); } return hash; } }.
Paulo, the intf you have designed solves the problem , now we need a Map that uses it! – mP. Mar 28 at 10:01 @mP: Yeah, I reimplemented most of the collection library to use these interfaces instead of equals/hashCode.
– PaÅlo Ebermann Jun 2 at 0:12.
A TreeSet actually performs ordering and Set based behavior using compare/compareTo and allows you to define a custom Comparator for use in one of the constructors.
This only works if you can define some total ordering on your elements. – PaÅlo Ebermann Jun 2 at 0:12.
You will not succeed doing your de-duplicating concatenation with a Comparator. Presumably you are looking to do something like this: List list = new ArrayList(); list. AddAll( a ); list.
AddAll( be ); Collections. Sort( list, new MyCustomComparator() ); The problem is that Comparator needs to compare not just for equals/not-equals, but also for relative order. Given objects x and y that are not equal, you have to answer if one is greater than the other.
You will not be able to do that, since you aren't actually trying to compare the objects. If you don't give a consistent answer, you will send the sorting algorithm into an infinite loop. I do have a solution for you.
Java has a class called LinkedHashSet, whose virtue is that it doesn't allow duplicates to be inserted, but maintains insertion order. Rather than implementing a comparator, implement a wrapper class to hold the actual object and implement hashCode/equals.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.