2

I currently have this piece of code:

Map<Site, LinkedList<Site.Hosts.Host>> map = new HashMap<Site, LinkedList<Site.Hosts.Host>>();

for (PerformanceCounter element : pc) {
  Site s = new Site();

  s.id = Short.parseShort(element.getSite_id());
  s.name = element.getSite_name();
  s.location = element.getSite_location();

  Site.Hosts.Host h = new Site.Hosts.Host();
  h.id = Short.parseShort(element.getHost_id());

  if (!map.containsKey(s)) {
    map.put(s, new LinkedList<Site.Hosts.Host>());
  } else {
    map.get(s).add(h);
  }
}

The list of PerformanceCounters that I am reading is:

1, C-01, New York, 1001
1, C-01, New York, 1002
1, C-01, New York, 1003

Where 101 is the id, C-01 is the name, and New York is the location.

Unfortunately, my code creates 3 key values for my Map.

I'm not able to generate 1 key with 3 values in the LinkedList.

My if( !map.containsKey(s) ) part isn't working correctly and I'm not sure how to fix this.

vkg
  • 1,839
  • 14
  • 15
user1413969
  • 1,261
  • 2
  • 13
  • 25
  • 3
    HashMap uses hashCode() and equals() to locate and compare keys. Have you overridden them? Can you show us their code? – JB Nizet May 09 '14 at 00:56
  • I didn't override either method. The thing I'm confused about is that my Site object has 4 fields: Short id, String name, String location, and Hosts host. I purposely left "host" to be null and the rest of the values are all the same. I'm not sure if the error is because my comparison fails when a Object field is left null. – user1413969 May 09 '14 at 01:02
  • 3
    If you didn't override equals() and hashCode(), then 2 instances of Site, even if all their fields are equal, will be different. Read the javadoc of Object.equals() and Object.hashCode(), make sure to understand what they do and what their contract is, and override them. Also note that using public fields is bad practice, and using a mutable class as a Map key is dangerous. – JB Nizet May 09 '14 at 01:05
  • If you don't override those methods, Map will use the default implementations which are based on object identity. So two Site objects containing identical values will be treated as different keys. – Brodo Fraggins May 09 '14 at 01:05

1 Answers1

6

Are you the author of Site.java class. If yes make sure you have correct implementation of hashCode() and equals() methods.

The basic contract for this to work correctly is:

  1. If two objects are equal as per equals() methods then they must have same hashCode().
  2. But if two objects return same hashCode() that does not mean that they will be equal.
  3. Further if you are using any object properties in evaluating hasCode() method they must be used in the equals() implementation as well.
vkg
  • 1,839
  • 14
  • 15
  • I generated that class from a xsd file by typing xjc in the terminal. Its rather big so I didn't post it, but it doesn't have hashcode or equals overrided. – user1413969 May 09 '14 at 01:04
  • If hashcode and equals is not there and still you want to use as key in map then you will have to add implementation of these two methods or else your map will not work. – vkg May 09 '14 at 01:05
  • 1
    See [generating-hashCode-and-equals](http://stackoverflow.com/questions/9062539/generating-hashcode-and-equals-when-creating-java-classes-using-mojo-jaxb2-m) discussion for an example of how to get xjc to generate these. – Martin Serrano May 09 '14 at 01:08
  • Your point 3 contradicts your point 2. You could very well compute the hashCode using field1 only, and implement equals using field1 and field2. – JB Nizet May 09 '14 at 01:12
  • @JBNizet I know what you mean. But the idea is to not have too many objects having same hashcode which in turn will result in slower retrievals. So you can say as a good practice :) – vkg May 09 '14 at 01:19
  • Then don't make it part of the contract of the methods. Strange that you insist on this, although what matters the most is the reverse: if a field is used in hashCode, then it must also be used in equals(). Otherwise, two equal values could have different hashCodes. – JB Nizet May 09 '14 at 01:22