amit modi
amit modi

Reputation: 1108

How to make class usable in different HashMaps in Java

I have a class Attribute which has 2 variables say int a,b;

I want to use class Attribute in two different HashSet.

The first hash set considers objects as equal when the value of a is same. But the second hash set considers objects as equal when the value of b is same.

I know if I override the equals method the hashset will use the overriden version of equals to compare two objects but in this case I would need two different implementations of equals()

One way is to create two subclasses of attribute and provide them with different equals method but I want to know if there is a better way to do it such that I dont have to create subclass of Attribute.

Thanks.

Upvotes: 0

Views: 465

Answers (6)

amit modi
amit modi

Reputation: 1108

I did some thing different, Instead of using the HashSet, I have used HashMap where I have used int a as a key in first HashMap and the object is stored as value. And in the other HashMap I have kept the key as int b and the object as value.

This provides me a way to Hash on both the variables a and b so I dont have to make any sub classes.

And also, I get O(1) time instead of O(log n). But I know I am paying the price by using some more memory but my main concern was time so I chose HashMap over TreeSet.

Thank you all for your comments and suggestions.

Upvotes: 1

Saurabh
Saurabh

Reputation: 7964

I can propose a bit hacky but lesser effort solution :) Swap the values of a and b when storing in second hashset so that uniqueness is defined by value of b and then when reading the class from hashset then swap the value of a and b again to retain the original state. So the same equals/hascode methods will serve the purpose.

Upvotes: 0

David Harkness
David Harkness

Reputation: 36562

A simple solution is to bypass HashSet and use HashMap directly. For the first, store each Attribute using its a property as the key, and for the other use b.

Upvotes: 0

David Harkness
David Harkness

Reputation: 36562

It would be very easy to modify HashMap and HashSet to accept hashing and equality-testing strategies.

public interface Hasher {
    int hashCode(Object o);
}

public interface Equalizer {
    int areEqual(Object o1, Object o2);
}

Upvotes: 0

Dylan
Dylan

Reputation: 13922

One possible solution is to not use HashSet, but use TreeSet instead. It's the same Set interface, but there is a TreeSet constructor that lets you pass in a Comparator. That way you could leave the Attribute class unchanged- just create two different comparators and use it like

Set<Attribute> setA = new TreeSet<Attribute>(comparatorForA);
Set<Attribute> setB = new TreeSet<Attribute>(comparatorForB);

The comparator takes care of the equality check (e.g. if compare returns 0, the objects are equal)

Upvotes: 3

G_H
G_H

Reputation: 12009

Unfortunately there's no "Equalizer" class that can override the equals logic. There is such a thing for sorting, where you can either use natural sorting based on the Comparable implementation or provide your own Comparator. I've actually wondered why there's no such thing for equality checks.

Since the semantics of equality are defined by a class and could be considered a trait of that class, the two subclasses approach seems the most natural. Maybe someone knows a useful pattern for doing this in a more simple manner, but I've never encountered it.

EDIT: just thought of something... you could use two Map instances, like HashMap, with the first one using a as key and the second using b as key. It'd let you detect collisions. You could then simply link the attribute to the associated instance.

Upvotes: 1

Related Questions