How to write hashcode() method in Java? - java

I've never had occasion to write a hashcode function in Java but now I have a need to do so. How do I go about it?
It's for an ArrayList and each element contains 5 Strings and nothing else.
I found an example for an ArrayList that contains 2 string and it's very simple:
return 31 * lastName.hashCode() + firstName.hashCode();
Can I get away with something equally simple, namely:
return 31 * field1.hashcode() + field2.hashcode() + field3.hashcode() + field4.hashcode() + field5.hashcode();
Or does a hashcode() method have further requirements?
I found another StackOverflow discussion of hashcode() here: Best implementation for hashCode method
From that, I imitated one of the answers and came up with this:
return Objects.hash(this.mClientCode, this.mOrderNumber, this.mOrderDate, this.mTicketsSold, this.mSellerName);
Is that better than the first one I suggested? Why?
Since hashcode() and equals() should apparently always get changed at the same time, this is my equals():
public boolean equals(Object o) {
if (!(o instanceof SalesItem)) {
return false;
}
SalesItem n = (SalesItem) o;
return n.mClientCode.equals(mClientCode) && n.mOrderNumber.equals(mOrderNumber) &&
n.mOrderDate.equals(mOrderDate) && n.mTicketsSold.equals(mTicketsSold) &&
n.mSellerName.equals(mSellerName);
}
Does that look okay?

Your equals is almost right. If none of those values can be null, its good. If they can be, then you need to add null checks as well- if((n.lastName!= null && n.lastName.equals(lastname)) || (n.lastName == null && lastname == null)) and repeat for the others.
For the hash- what you want is the has to be as randomly distributed as possible and unique for the values you would consider unique. Its hard for us to tell you a good hash algorithm because we don't know how your data structure is used. For example, if there's only 4 sellers, you'd want that field to be a very small factor in the hash, if a factor at all.
Is this a representation of a database row? It looks like one. Because if it is, the rowId or a UUID for the row would be the best thing to hash.

You can also use the HashCodeBuilder in the org.apache.commons.lang3 library.
Here is the documentation and an example:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html

Related

Is there an easy way to compare scheme:host:port part of URI's to see if they are equal?

If I have two URI's, is there an easier way to compare the base URI rather than having to do the following?
URI firstURI = new URI("https://localhost:8000");
URI secondURI = new URI("https://localhost:8000/testing");
if (!firstURI.getHost().equals(secondURI.getHost()) ||
!firstURI.getScheme().equals(secondURI.getScheme()) ||
firstURI.getPort() != secondURI.getPort())
{
//error
}
You could have used the URI.equals() method but it doesn't suit at all to your requirement as it relies on really different rules.
Here is an extract of :
For two URIs to be considered equal requires that either both are
opaque or both are hierarchica*. Their schemes must either both be
undefined or else be equal without regard to case. Their fragments
must either both be undefined or else be equal.
So you don't have really the choice : create a utility method and use it such as :
public boolean isURIMatch(URI firstURI, URI secondURI){
if (!firstURI.getHost().equals(secondURI.getHost()) ||
!firstURI.getScheme().equals(secondURI.getScheme()) ||
firstURI.getPort() != secondURI.getPort()) {
return false;
}
return true;
}
You can shorten it slightly by comparing the values of getAuthority(), which returns everything between the scheme and path:
if (!firstURI.getAuthority().equals(secondURI.getAuthority()) ||
!firstURI.getScheme().equals(secondURI.getScheme()))
Be aware that the authority also includes the user info (username and password), but few URLs use that anymore, so unless you’re expecting URIs with login information in them, the above comparison should be safe.

Efficient null check for a compound object in Java [duplicate]

This question already has answers here:
is there a Java equivalent to null coalescing operator (??) in C#? [duplicate]
(5 answers)
Null check chain vs catching NullPointerException
(19 answers)
Closed 6 years ago.
A program creates a JDialog panel with multiple tabs. One of the tabs has several tables. A JTable has adjustable column width. This tab is generated under different conditions. Sometimes from the state tab is null, sometimes tab exists, but the table is null. Sometimes user haven't resized the column yet.
I am looking for a method to save the columnWidth value if user resized the column. Checking for null seems bulky in this situation:
jpanel.tab.table.width
the best method I can find is:
if( jpanel!=null &&
jpanel.jtab!=null &&
jpanel.jtab.jtable!=null && ...
Is there a better way to do this null check?
I saw this question:
is there a Java equivalent to null coalescing operator (??) in C#?
It doesn't list a solution and is quite old (Java 6-7 time). I was hoping this feature was added in later releases.
There's no way to do exactly what you want.
However, you can just throw everything into a try statement:
try {
myItem = bundle.category.subcategory.item;
}
catch(NullpointerException ignored) {}
Note that this looks very hacked, and it's rather poor coding practice. Your current solution is probably the best approach in terms of clarity.
Edit: I tried posting another Anwser but the button is greyed out, so I'll put it here:
Feels like repeating same code many times, when you should use a for loop
You can indeed use a for loop, but that will invovle Reflection and much boilerplate code. Imagine something like this:
static boolean checkDeepNull(Object root, String... attributes) throws NoSuchFieldException, IllegalAccessException {
Object currentAttribute = root;
for(int attr = 0; currentAttribute != null && attr < attributes.length; attr++){
Field nextField = currentAttribute.getClass().getField(attributes[attr]);
Object nextAttribute = nextField.get(current);
if(nextAttribute == null) return false;
currentAttribute = nextAttribute;
}
return true;
}
How to use it: if(checkDeepNull(bundle, "category", "subcategory", "item"))
You could have an interface which determines nullability:
public interface Nullability {
public boolean hasNulls();
}
And then simply have the parent call any children like so:
public boolean hasNulls() {
return this.bundle == null || bundle.hasNulls();
}
//in bundle
public boolean hasNulls() {
return this.category == null || category.hasNulls();
}
Regardless, if you have to nullcheck everything, you're going to be doing a lot of boilerplate code if you don't provide a means of iteration. That's what you should really focus on.
On a personal level, I disagree heavily with exposing fields like that. It's a very easy way to lead to more headaches and errors in design.
The short answer is no.
Can you redesign bundle so that it is always fully constructed? I.e., if bundle != null, then category, subcategory and item always exist? This could also help with concurrency issues. Basically, if nulls give you problems, where possible, don't allow these fields to be null.
Another option is the Null Object Pattern. Basically, you have a "default" implementation of Bundle which always return getCategory() that always returns a value for getSubcategory(), but ultimately the call to getItem() returns null or something to indicate "nothing". This is a great pattern but requires some work.
I hesitate to suggest it, but it is rare for any of the items to be null, at some point it may be faster and clearer to just catch the NPE, but this style should really be avoided. And it is a definite code smell that your design is poor. Avoid it if at all possible.
try {
return foo.bar.bap.zaz.blah.blah;
}
catch (NullPointerException ignored) {
return null;
}

Cyclomatic Complexity, joining conditions and readability

Consider the following method (in Java - and please just ignore the content):
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null) {
return false;
}
if (getClass() != object.getClass()) {
return false;
}
if (hashCode() != object.hashCode()) {
return false;
}
return true;
}
I have some plugin that calculates: eV(g)=5 and V(g)=5 - that is, it calculates Essential and common CC.
Now, we can write the above method as:
public boolean equals2(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
return hashCode() == object.hashCode();
}
and this plugin calculates eV(g)=3 and V(g)=3.
But how I do understand CC, the values should be the same! CC is not about counting the lines of code, but the independent paths. Therefore, joining two if in one line does not really reduces CC. In fact, it only can make things less readable.
Am I right?
EDIT
Forgot to share this small convenient table for calculating CC quickly: Start with a initial (default) value of one (1). Add one (1) for each occurrence of each of the following:
if statement
while statement
for statement
case statement
catch statement
&& and || boolean operations
?: ternary operator and ?: Elvis operator.
?. null-check operator
EDIT 2
I proved that my plugin is not working well, since when I inline everything in one line:
public boolean equals(Object object) {
return this == object || object != null && getClass() == object.getClass() && hashCode() == object.hashCode();
}
it returns CC == 1, which is clearly wrong. Anyway, the question remains: is CC reduced
[A] 5 -> 4, or
[B] 4 -> 3
?
Long story short...
Your approach is a good approach to calculate CC, you just need to decide what you really want to do with it, and modify accordingly, if you need so.
For your second example, both CC=3 and CC=5 seem to be good.
The long story...
There are many different ways to calculate CC. You need to decide what is your purpose, and you need to know what are the limitations of your analysis.
The original definition from McCabe is actually the cyclomatic complexity (from graph theory) of the control flow graph. To calculate that one, you need to have a control flow graph, which might require a more precise analysis than your current one.
Static analyzers want to calculate metrics fast, so they do not analyze the control flow, but they calculate a complexity metric that is, say, close to it. As a result, there are several approaches...
For example, you can read a discussion about the CC metric of SonarQube here or another example how SourceMeter calculates McCC here.
What is common, that these tools count conditional statements, just like you do.
But, these metrics wont be always equal with the number of independent execution paths... at least, they give a good estimation.
Two different ways to calculate CC (McCabe and Myers' extension):
V_l(g) = number of decision nodes + 1
V_2(g) = number of simple_predicates in decision nodes + 1
If your goal is to estimate the number of test cases, V2 is the one for you. But, if you want to have a measure for code comprehension (e.g. you want to identify methods that are hard to maintain and should be simplified in the code), V1 is easier to calculate and enough for you.
In addition, static analyzers measure a number of additional complexity metrics too (e.g. Nesting Level).
Converting this
if (hashCode() != object.hashCode()) {
return false;
}
return true;
to this
return hashCode() == object.hashCode();
obviously reduces CC by one, even by your quick table. There is only one path through the second version.
For the other case, while we can't know exactly how your plugin calculates those figures, it is reasonable to guess that it is treating if (object == null || getClass() != object.getClass()) as "if a non-null object's class matches then ...", which is a single check and thus adds just one to CC. I would consider that a reasonable shortcut since null checks can be rolled up into "real" checks very easily, even within the human brain.
My opinion is that the main aim of a CC-calculating IDE plugin should be to encourage you to make your code more maintainable by others. While there is a bug in the plugin (that inlined single-line conditional is not particularly maintainable), the general idea of rewarding a developer by giving them a better score for more readable code is laudable, even if it is slightly incorrect.
As to your final question: CC is 5 if you strictly consider logical paths; 4 if you consider cases you should consider writing unit tests for; and 3 if you consider how easy it is for someone else to quickly read and understand your code.
In the second method
return hashCode() == object.hashCode(); costs 0 so you win 1. It's considered as calculation and not logical branch.
But for the first method I don't know why it's cost 5, I calculate 4.
As far as style is concerned, I consider the following the most readable:
public boolean equals(Object object) {
return this == object || (object != null && eq(this, object));
};
private static boolean eq(Object x, Object y) {
return x.getClass() == y.getClass()
&& x.hashCode() == y.hashCode(); // safe because we have perfect hashing
}
In practice, it may not be right to exclude subclasses from being equal, and generally one can not assume that equal hash codes imply equal objects ... therefore, I'd rather write something like:
public boolean equals(Object object) {
return this == object || (object instanceof MyType && eq(this, (MyType) object));
}
public static boolean eq(MyType x, MyType y) {
return x.id.equals(y.id);
}
This is shorter, clearer in intent, just as extensible and efficient as your code, and has a lower cyclomatic complexity (logical operators are not commonly considered branches for counting cyclomatic complexity).

Searching through a collection of an array list pair [duplicate]

This question already has answers here:
How to compare two java objects [duplicate]
(5 answers)
Closed 9 years ago.
I am trying to search through a collection of an ArrayList if pairs. What I want to be able to do, is to go through the collection and find the first value in a pair and return the second value of that pair. The problem I am having is that the check I have to find the first value doesn't seem to be working, so every time I search, I end up returning null. I know that the problem exists with my if statement, but I cannot seem to sort out what it is I am doing wrong. Since this is a homework assignment, I can't show all the code to my pair class, or my pair list class, but I can show you the method I have for searching the first value:
public S findFirst(F firstValue) {
Iterator<Pair> myIter = this.iterator();
S tmp2 = null;
while (myIter.hasNext()) {
Pair tmp1 = myIter.next();
if (tmp1.getFirst() == firstCall) {
tmp2 = (S) tmp1.getSecond();
}
}
return tmp2;
}
If I throw in an else statement that just calls what I am attempting to do in my if check, like this:
else{
tmp2 = (S) tmp1.getSecond();
}
then whenever I test for the first value, I get the second value, so I know I am at least on the correct path, but I am assuming that I am doing something wrong with what I am checking for in my if statement. Does anyone know how I can correctly do this, (and please bear in mind that this is homework, so a guide to how to figure this out is far more valuable to me than just some random answer, I want to learn, not just be given an answer) Thanks in advance!
Don't use == to compare objects. Override and use equals().
I think
if (tmp1.getFirst() == firstCall)
should probably say
if (tmp1.getFirst().equals(firstValue))
The important difference is that == checks whether two expressions refer to the exact same object. You're more interested in knowing whether your two expressions actually refer to objects that are equal.
Try this:
if (tmp1.getFirst().equals(firstValue))
instead of
if (tmp1.getFirst() == firstCall)
Also you can override your own equals method.
You should never use == to compare objects.
Check How to compare two java objects
What Matt says, (don't use == ) but I think a bigger problem is that you don't return the 'first' encounter.... your if statement should look like:
public S findFirst(F firstValue) {
Iterator<Pair> myIter = this.iterator();
while (myIter.hasNext()) {
Pair tmp1 = myIter.next();
if (firstValue.equals(tmp1.getFirst())) {
return (S) tmp1.getSecond();
}
}
return null;
}

Grails: Checking whether a detached object is in an attached Set

The session of my application contains a user objects which has a settings objects which contains an attribute "effectiveOrganisation". The settings objects is loaded eagerly and since the Hibernate Session is per request, the user object in the session is detached from the Hibernate Session.
I want to check wheter the "effectiveOrganisation" is in the Set of an attached object:
<g:if test="${session.user.settings.effectiveOrganisation in
documentInstance.downloadingOrganisations}">
But the result of this test is always false. Maybe this is because the organisation in the session and the organisation of the documentInstance are not identical objects. I implemented equals and hashCode in the Organisation class but it didn't help.
I tried the following test in a controller:
def org = session.user.settings.effectiveOrganisation
doc.downloadingOrganisations.each{
if(it.equals(org))
println("equals works")
}
if(! doc.downloadingOrganisations.contains(org))
println("contains doesn't work")
The surprising result is:
equals works
contains doesn't work
equals and hashCode looks as follows:
boolean equals(o) {
if (this.is(o)) return true;
if (getClass() != o.class) return false;
Organisation that = (Organisation) o;
if (name != that.name) return false;
if (selfInspecting != that.selfInspecting) return false;
return true;
}
int hashCode() {
int result;
result = (name != null ? name.hashCode() : 0);
result = 31 * result + (selfInspecting != null ? selfInspecting.hashCode() : 0);
return result;
}
How can I check wheter an object from the session is contained in the set of an attached object?
It looks like your hashcode computation is probably the issue. Hashcode is usually a lot cheaper to calculate than equals, so it's compared first. If there's a collision and two different objects generate the same hashcode, then equals() is checked. But if two objects have different hashcodes then according to the hashcode/equals contract they are assumed to be different objects.
The instances in the collection are proxies - is that affecting the hashcode calculation?
Check the class of the instances. The hash code is probably not the issue, but the objects are most likely hibernate proxies which is the issue.
Check if equals() is being called during contains()
Also, changing this g:if to
g:if test="${session.user.settings.id in
    documentInstance.downloadingOrganisations*.id}"
May fix it.

Categories