2
\$\begingroup\$

I have a class Fighter in a software for planning boxing events. I implemented its hashCode() and equals() since I collect them in various data structures in many places.

Now I want to persist specific planned boxing events which themselves contain the same Fighters in different lists. I am using JAXB for this purpose.

In order not to have duplication in the XML nodes I made use of @XmlID and @XmlIDREF such that only once the whole Fighter data is stored – but referenced in other places. The code for the id is simple and it works as expected:

@XmlID
@XmlAttribute
public String getId() {
    return Integer.toString(hashCode());
}

(I was also searching for an auto-mechanism to generate those ids by JAXB but could not find anything which would be simpler as the solution above. Please tell me, if there is such a solution!)

The hashCode method looks as follows:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result =
        prime * result + ((firstNameProperty == null) ? 0 : firstNameProperty.get().hashCode());
    result = prime * result + ((lastNameProperty == null) ? 0 : lastNameProperty.get().hashCode());
    result = prime * result + ((genderProperty == null) ? 0 : genderProperty.get().hashCode());
    result = prime * result + ((birthdayProperty == null) ? 0 : birthdayProperty.get().hashCode());
    result = prime * result + ((clubProperty == null) ? 0 : clubProperty.get().hashCode());
    long temp;
    temp = Double.doubleToLongBits((weightProperty == null) ? 0 : weightProperty.get());
    result = prime * result + (int) (temp ^ (temp >>> 32));
    result = prime * result + ((winsProperty == null) ? 0 : winsProperty.get());
    result = prime * result + ((lossesProperty == null) ? 0 : lossesProperty.get());
    result = prime * result + ((drawsProperty == null) ? 0 : drawsProperty.get());
    return result;
}

And the class member variables which are used here:

private StringProperty firstNameProperty;
private StringProperty lastNameProperty;
private ObjectProperty<Gender> genderProperty;
private StringProperty clubProperty;
private ObjectProperty<LocalDate> birthdayProperty;
private DoubleProperty weightProperty;
private IntegerProperty winsProperty;
private IntegerProperty lossesProperty;
private IntegerProperty drawsProperty;

My rationale was that hashCode() would give me a unique id for every fighter and is already there.

What do you think about that? Are there any drawbacks I just don't see? Is it common to do it this way? Is there a far better solution?

\$\endgroup\$
1
\$\begingroup\$

Thanks for including the hashCode() method. As I suspected, the purpose of the hashCode method is to fulfil the equals/hashCode contract, and is not suitable for being an ID. For example, by changing the number of wins, you change the hashCode, and by proxy you change the player's ID.

If you want the ID to be a temporary thing that is only constant for the short time that the player is constant, then your solution is OK. If you want the ID to last through a persist/restore cycle, or even from one moment to the next when they pee .... and their weight changes, then you need a different system.

In addition, while you claim your hashCode is unique, it is not technically true. The chances of their being a duplicate are remote, but it is possible that two players will have the same hashCode, and hence the same ID.

In reality, your system is not reliable, and the best solution would be to create an externally managed ID for each player - a record number from a database, a unique counter, or something.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer! Regarding a externally managed ID: The thing is, that there is none and it is also not needed per se. I only need the ID in order to be able to use the @XmlIDREF and do not have to duplicate my XML nodes, so I only need it to be consistent within my XML file but nothing more. But I see your point and I think I will take sth. like a timestamp on creation time then ... \$\endgroup\$ – philonous Aug 25 '15 at 15:30
  • 1
    \$\begingroup\$ In that case, consider a UUID: randomUUID() \$\endgroup\$ – rolfl Aug 25 '15 at 15:33
  • \$\begingroup\$ In case one wants to have a schema validation the id generated from randomUUID() should be prefixed with a string that allows the id to be a "NCName" as for instance "id_". More information on this can be found e.g. here. \$\endgroup\$ – philonous Sep 3 '15 at 11:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.