Earlier on, in this thread my question was answered about how to add objects of a custom class I called State into a HashSet which was a value for a key in a HashMap.

Map<String, HashSet<State>> mapping = new HashMap<String, HashSet<State>>();

However, I need to ensure that there are only distinct State objects in this HashSet. The way that I know they are distinct is by a char that is stored within a State. However, the HashSet does not know that.
Can we please discuss a clear explanation of:

  1. The default behavior of a HashSet to ensure that the Set implementation functions
  2. How to change up my State class so that the HashSet knows on which value to check to ensure distinctness

This would be of great conceptual help to me for the future. Thank you!

Recommended Answers

All 5 Replies

The API doc for HashSet shows it to be a subclass of Set, and the API doc for Set says "More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2)"

So there's your answer. The implementation uses the equals(...) method of your objects to see if they are distinct. All classes inherit an equals method from Object, which tests them for being exactly the same instance. Many classes override this (eg String tests for both Strings containing the same sequence of chars). You can override equals for your State class and return a result based on the magic char that they contain.

ps: The answer to most questions is in the API doc. If it's really obscure you can download the source code for the whole API from Oracle and see how it really works.

pps: re overriding equals...
* Note that it is generally necessary to override the {@code hashCode}
* method whenever this method is overridden, so as to maintain the
* general contract for the {@code hashCode} method, which states
* that equal objects must have equal hash codes.

In your case then simply returning the magic char should do it?

Thank you. That makes sense. I did try to look at the API first - but I only looked at HashSet, and didn't think to look at Set. That will help me (and save you time!) in the future - to look thoroughly the the hierarchy of all the classes in the API and not just the one I'm using.

Would you say something like this would work within State?

public boolean equals(Object o)
	{
		if(((State)o).getStateName().equalsIgnoreCase(getStateName()))
			return true;
		return false;
	}

And to be honest - I don't much care if it's a HashSet or a TreeSet or any type of set - I just need some set functionality, and it is only very few States that I am working with - so maybe it would be easier to work with a TreeSet?

What kind of set is only important if you have biggish sets or high transaction volumes. You don't need a TreeSet unless you are orried about keeping the netries sorted.
That code looks OK to me - could be simpler...
return ((State)o).getStateName().equalsIgnoreCase(getStateName());

Ahh, making more sense now. I ended up just using a TreeSet because I didn't want to fuss with Hash stuff right now. I had to also implement the compareTo method within State, which now looks as if it's working.

Sometimes it is difficult to know just which methods I need to implement to get something working to my desires, which is why I am asking these questions. With a little try and fail and help from you, however, it is working.

Thanks!

Glad to help! Good luck. J.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.