user1096463
user1096463

Reputation:

Is there a Map I can use that will prevent .equals() duplicates?

I want a Map<?, ?> which will prevent duplicates, but not only memory duplicates, but duplicates where everything in the object has the same value, i.e. where .equals() == true. Anyone know how I can achieve this?

Upvotes: 0

Views: 83

Answers (2)

Joop Eggen
Joop Eggen

Reputation: 109567

You are searching a birectional mapping, use Guava's BiMap.

That is: mapping as a bijective function:

y = map.get(x)
x = map.inverse.get(y)

Correction:

As @JoshuaTaylor commented, it seems I have misunderstood the question.

Just maybe, maybe, what really is wanted though, is having no multiple instances of equal objects.

class Unique {

    private static Map<Object, Object> identityMap = new HashMap<>();

    public static <T> T share(T object, Class<T> type) {
        Object old = identityMap.get(object);
        if (old == null) {
            old = object;
            identityMap.put(old, old);
        }
        return type.cast(old);
    }
}

With usage:

Xxx x = ...
x = Unique.share(x, Xxx.class);

Which causes x to be the first equal instance.

Probable a weak reference map would be nicer.

Upvotes: 0

Joshua Taylor
Joshua Taylor

Reputation: 85863

The Map interface specifies that the comparison of keys is equality (.equals):

public interface Map<K,V>

public V get(Object key)

…. More formally, if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)

Of course, that's documentation of the interface. The Java type system can't actually enforce that that behavior holds. Most implementations of Map respect it, though. For instance, that's the behavior you'll see in a HashMap.

There is an implementation of Map that is based on identity (==) rather than equality (.equals), though. It's called IdentityHashMap. Its documentation explicitly calls out the fact that this behavior is not typical for implementations of Map, and that, in fact, it violates the contract of Map (emphasis present in original):

public class IdentityHashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Serializable, Cloneable

This class is not a general-purpose Map implementation! While this class implements the Map interface, it intentionally violates Map's general contract, which mandates the use of the equals method when comparing objects. This class is designed for use only in the rare cases wherein reference-equality semantics are required.

Upvotes: 2

Related Questions