views:

111

answers:

7

Here I have some value which two of them are integer and I can't call a method on them since they are not reference. How can I solve this?

String srcAddr, dstAddr, protocol;
int srcPort, dstPort;

public int hashCode() {

        final int prime = 31;
        int result = 1;
        result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
        result = prime * result + ((dstPort == null) ? 0 : dstPort.hashCode());
        result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
        result = prime * result + ((srcPort == null) ? 0 : srcPort.hashCode());
        return result;

}

Also, I have an equal method too, a part of it with the error is shown below ,which the same as above I can not compare int with a null.

@Override
public boolean equals(Object obj) {

    if (srcPort == null) {
        if (other.srcPort != null)
            return false;
    } else if (!srcPort.equals(other.srcPort))
        return false;

    if (srcPort == null) {
        if (other.srcPort != null)
            return false;
    } else if (!srcPort.equals(other.srcPort))
        return false;
}

How can I solve this error?

A: 

You need to use the boxed primitives, specifically Integer. There's a similar object for each primitive, and they define the methods you're interested in (hashCode,equals).

Shakedown
A: 

Initalise the integers to something (say -1) and compare them to -1

I don't see why you want to get the Hashcode of an integer. Hashcode takes an object and returns a unique(?) integer based on the object. An integer is just a primitive object and you should need to get a hashcode from it to identify it.

I would just refer to the integers directly and have a check for -1 (if you initialise them to -1) instead of a check to null. (It is my understanding that a port is never -1, do correct me if this is false)

Raynos
`hashCode()` does not return a unique integer for each object. (That's impossible - if you could encode the state of any object in a 32-bit integer you're breaking information theory laws).
Jesper
+2  A: 

For the hashcode method, you can just leave the ints as they are. Ints are their own hascodes. For the equals method, just compare them using =. So the code becomes:

public class Connection {

    String srcAddr, dstAddr, protocol; int srcPort, dstPort;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
        result = prime * result + dstPort;
        result = prime * result
                + ((protocol == null) ? 0 : protocol.hashCode());
        result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
        result = prime * result + srcPort;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Connection other = (Connection) obj;
        if (dstAddr == null) {
            if (other.dstAddr != null)
                return false;
        } else if (!dstAddr.equals(other.dstAddr))
            return false;
        if (dstPort != other.dstPort)
            return false;
        if (protocol == null) {
            if (other.protocol != null)
                return false;
        } else if (!protocol.equals(other.protocol))
            return false;
        if (srcAddr == null) {
            if (other.srcAddr != null)
                return false;
        } else if (!srcAddr.equals(other.srcAddr))
            return false;
        if (srcPort != other.srcPort)
            return false;
        return true;
    }

}

Writing correct implementations of hashCode and equals is tricky. Better use your IDE to generate them. That's what I did here too.

abhin4v
+4  A: 

Writing hashcode and equals can be tedious and/or error-prone, and IDEs such as Eclipse can actually automate this task for you. There are many third party libraries that can facilitate this functionality as well.

To use something from the standard library, I recommend doing the following:

import java.util.Arrays;

// conveniently packs varargs to array 
private static Object[] pack(Object... objs) {
   return objs;
}

private Object[] fieldsAsArray() {
   return pack(srcAddr, dstAddr, protocol, srcPort, dstPort);
}

@Override public int hashCode() {
   return Arrays.hashCode(this.fieldsAsArray());
}

@Override public boolean equals(Object o) {
   // TODO: instanceof check, cast and assign o to other

   return Arrays.equals(this.fieldsAsArray(), other.fieldsAsArray());
}

This uses varargs, autoboxing, and java.util.Arrays utility method implementation for equality and hashcode of arrays. This will have an adequate (though perhaps not optimal) performance, but the code is succint and readable, and can always be optimized later if/when necessary.


Third party library options

From Apache Commons Lang, you can use EqualsBuilder and HashCodeBuilder.

The documentation has example of typical usage:

@Override public boolean equals(Object obj) {
   if (obj == null) { return false; }
   if (obj == this) { return true; }
   if (obj.getClass() != this.getClass()) {
     return false;
   }
   MyClass other = (MyClass) obj;
   return new EqualsBuilder()
                 .appendSuper(super.equals(obj))
                 .append(field1, other.field1)
                 .append(field2, other.field2)
                 .append(field3, other.field3)
                 .isEquals();
}

@Override public int hashCode() {
   return new HashCodeBuilder(17, 37)
                 .append(field1)
                 .append(field2)
                 .append(field3)
                 .toHashCode();
} 

The resulting code is very readable, very maintainable, and less error prone.

Related questions

polygenelubricants
A: 

srcPort and dstPort are primitive ints.

In your hashCode() method, you are comparing dstPort and srcPort to null. You can't do that with primitive types in Java. Just write the lines in your hashCode() method like this:

result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + dstPort;
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + srcPort;

In your equals() method, you are trying to call the equals() method on srcPort. You cannot call methods on primitive types in Java. Use == to compare pritimive types.

Note that your equals() method also contains the same block of code twice; this is most likely a mistake. And don't you have to check srcAddr and dstAddr as well in your equals() method? What is other in your equals() method? Is this the complete code or only part of it?

Jesper
thanks for your answer. yes it was a part of mycode and other is "Flows other = (Flows) obj;"I got the point and I understood what was my problem.
Red Lion
A: 

There are two problems here. First, ints declared at the class level as instance or class variables are always initialized to a value. It doesn't matter what that value is, they are defined to be something, even if you don't explicitly do it. Second, it makes no sense to call hashCode() on something that is a primitive type as these don't have methods you can invoke.

My implementation would look something like this:

public int hashCode() {

        final int prime = 31;
        int result = 1;
        result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
        result = prime * result + dstPort;
        result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
        result = prime * result + srcPort.hashCode;
        return result;

}

public boolean equals(Object obj) {
    if (!(obj instanceof MyClass)) {
        return false;
    }

    //Cast obj to a MyClass

    if (other.srcPort != scrPort) {
            return false;
    }

    if (other.dstPort != dstPort) {
            return false;
    }

    //Check the other variables too.

    //We didn't fall into any if-statements.
    return true;
}
Thomas Owens
Untrue. An uninitialized int in a method remains uninitialized just like ant other variable.
EJP
That is a true statement. However, his `int`s are declared outside of the method. I will revise my post to make that explicitly clear.
Thomas Owens
A: 

I think Shakedown has the answer for you, just used the boxed Integer type like so:

String srcAddr, dstAddr, protocol; Integer srcPort, dstPort;

public int hashCode() {

    final int prime = 31;
    int result = 1;
    result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
    result = prime * result + ((dstPort == null) ? 0 : dstPort);
    result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
    result = prime * result + ((srcPort == null) ? 0 : srcPort);
    return result;

}

or alternatively use 0 as a default value (since that's what you return if the value isn't set anyway) like so:

String srcAddr="", dstAddr=""; int srcPort=0,dstPort=0; //empty string has hashCode 0

public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + dstAddr.hashCode();
  result = prime * result + dstPort;
  result = prime * result + srcAddr.hashCode();
  result = prime * result + srcPort;
  return result;
}

This way you don't need to worry about the implicit cost of auto-boxing if that is an issue

Asaf
_Effective Java 2nd Edition, Item 49: Prefer primitives to boxed primitives_. Boxing to `Integer` is convenient/necessary at times, but I wouldn't recommend having it for fields.
polygenelubricants