Populating a TreeMap throws NullPointerException - java

I am getting a NullPointerException while creating a TreeMap.
Here is my code:
public TreeMap<AccountGroupBean,List<AccountBean>> getAccountsAndGroups() throws SessionExpiredException {
TreeMap<AccountGroupBean,List<AccountBean>> map = new TreeMap<AccountGroupBean,List<AccountBean>>();
List<AccountGroupBean> groups = getAccountGroups();
for(AccountGroupBean group : groups) {
List<AccountBean> accounts = getAccountsByGroupId(group.getId());
System.out.println("PRINT"+ accounts.size());
map.put(group,accounts);
System.out.println("!" +map.get(group).size());
}
return map;
}
The first println prints 44. That it is to say is not null. However, the second println raises the null exception.
Any idea what I am doing wrong?
Solution
AS pointed in the accepted solution. The problem was in my implementation of compareTo.
I used to have:
public int compareTo(AccountGroupBean o) {
return (number > o.getNumber()) ? 1 : -1;
}
Adding a 0 return solved the issue:
public int compareTo(AccountGroupBean o) {
if(number == o.getNumber()) {
return 0;
}
return (number > o.getNumber()) ? 1 : -1;
}

I looks like AccountGroupBean doesn't implement Comparable in a proper way, try to println group.compareTo(group) to check if it prints 0.

This is most likely a problem with how the AccountGroupBean class is implementing equals and hashcode. There are some rules fro implementing equals and hashcode that you should make sure your code complies to. Some of the rules for the equals method include.
Reflexive for any non null value x.equals(x) is always true
Symetric for non null values y.equals(x) must return true if and only if x.equals(y) is true
Transitive for non null values if x.equals(y) is true and y.equals(z) is true then x.equals(z) must also be true
Consistant The equals method should return the same answer during multiple invocations if the objects have not been modfied.
If two objects are equal their hashcoe method should return the same value.

Related

How can I junit test the last block of this equal?

How can I JUnit test the last block of this equal?
Any help would be much appreciated. This is the method in question:
#Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
//unreachable block
ServiceOrderRelationship serviceOrderRelationship = (ServiceOrderRelationship) o;
return Objects.equals(this.id, serviceOrderRelationship.id) &&
Objects.equals(this.href, serviceOrderRelationship.href) &&
Objects.equals(this.relationshipType, serviceOrderRelationship.relationshipType) &&
Objects.equals(this.baseType, serviceOrderRelationship.baseType) &&
Objects.equals(this.schemaLocation, serviceOrderRelationship.schemaLocation) &&
Objects.equals(this.type, serviceOrderRelationship.type) &&
Objects.equals(this.referredType, serviceOrderRelationship.referredType);
}
This is what I've been doing but I can never reach the last block of code inside the equals method:
#Test
public void testEquals() throws Exception {
assertFalse(serviceOrderRelationship.equals(null));
assertTrue(serviceOrderRelationship.equals(serviceOrderRelationship));
assertFalse(serviceOrderRelationship.equals(serviceOrderRelationship1));
}
First of all, thank you all for your responses!
This is how I was able to reach the last block of the equals method. I had to initialize both objects di and di1 and set every variable to the same value, then test the equals condition switching back and forth one variable at a time to a different value. This is an example from another POJO:
// Initialize objects
di.setEdgeId("edgeId");
di.setIdentityEndpoint("identityEndpoint");
di.setUsername("username");
di1.setEdgeId("edgeId");
di1.setIdentityEndpoint("identityEndpoint");
di1.setUsername("username");
// Change value of var and test equal
di1.setEdgeId("edgeIdm");
assertFalse(di.equals(di1));
di1.setEdgeId("edgeId");
// same
di1.setIdentityEndpoint("identityEndpointm");
assertFalse(di.equals(di1));
di1.setIdentityEndpoint("identityEndpoint");
// Same
di1.setUsername("usernamem");
assertFalse(di.equals(di1));
di1.setUsername("username");
// Then at the end perform the other tests
assertTrue(di.equals(di));
assertTrue(di.equals(di1));
assertFalse(di.equals(null));
assertFalse(di.equals(42));
Your problem might be that one of the follow cases, in which the method would return prematurely.
If serviceOrderRelationship and serviceOrderRelationship1 are references to the same object, the true would be returned. Similarly, if they are not of the same type, false would be returned. If serviceOrderRelationship1 is null, false would be returned.
If serviceOrderRelationship is null, then calling equals on it would throw a NullPointerException.

Does java.util.HashSet not Adhere to its Specification?

As a relative Java noob, I was baffled to find out the following:
Point.java:
public class Point {
...
public boolean equals(Point other) {
return x == other.x && y == other.y;
}
...
}
Edge.java:
public class Edge {
public final Point a, b;
...
public boolean equals(Edge other) {
return a.equals(other.a) && b.equals(other.b);
}
...
}
main snippet:
private Set blockedEdges;
public Program(...) {
...
blockedEdges = new HashSet<Edge>();
for (int i = 0; ...) {
for (int j = 0; ...) {
Point p = new Point(i, j);
for (Point q : p.neighbours()) {
Edge e = new Edge(p, q);
Edge f = new Edge(p, q);
blockedEdges.add(e);
// output for each line is:
// contains e? true; e equals f? true; contains f? false
System.out.println("blocked edge from "+p+"to " + q+
"; contains e? " + blockedEdges.contains(e)+
" e equals f? "+ f.equals(e) +
"; contains f? " + blockedEdges.contains(f));
}
}
}
}
Why is this surprising? Because I checked the documentation before I coded this to rely on equality and it says:
Returns true if this set contains the specified element. More
formally, returns true if and only if this set contains an element e
such that (o==null ? e==null : o.equals(e))
This sentence is very clear and it states that nothing more than equality is needed. f.equals(e) returns true as shown in the output. So clearly the set does indeed contain an element e such that o.equals(e), yet contains(o) returns false.
While it is certainly understandable that a hash set also depends on the hash values being the same, this fact is mentioned neither in the docs of HashSet itself, nor is any such possibility mentioned in the docs of Set.
Thus, HashSet doesn't adhere to its specification. This looks like a very serious bug to me. Am I completely on the wrong track here? Or how come behaviour like this is accepted?
You're not overriding equals (you're overloading it). equals need to accept an Object as argument.
Do something like
#Override
public boolean equals(Object o) {
if (!(o instanceof Point))
return false;
Point other = (Point) o;
return x == other.x && y == other.y;
}
(and same for Edge)
It's also important to always override hashCode when you're overriding equals. See for instance Why do I need to override the equals and hashCode methods in Java?
Note that this mistake would have been caught by the compile if you had used #Override. This is why it's good practice to always use it where possible.

How do I compare the "state" of two objects of the same type?

I'm supposed to create my own equals() method which overrides the equals(method) of the parent class. This method accepts a Counter object as its argument. In the code below, I want an easy way to determine if the Counter object argument equals the current instance of the Counter class, if that makes sense. I have achieved this in the code below by comparing the fields of each object one by one, but I want a simpler way to do it. Something that looks like this would be nice: "result = (otherCounter == new Counter(min,max) ? true : false);", but I know that's not right and it gets an error. How do I compare the equality of the variables in the two Counter objects, so that c1.equals(c2) will be false if Counter objects c1 and c2 are different?
public boolean equals(Object otherObject)
{
boolean result = true;
if (otherObject instanceof Counter)
{
Counter otherCounter = (Counter)otherObject;
result = (otherCounter.min == this.min) &&
(otherCounter.max == this.max) &&
(otherCounter.currentCount == this.currentCount) &&
(otherCounter.rolloverOccurrence == this.rolloverOccurrence) ? true : false;
}
return result;
}
Operator overloading is not possible in Java.
And to compare two object are equal or not you should use .equals() method no matter what.
Ex: obj1.equals(obj2)
It is because sometimes Java API (ex: Collections) will internally call equals method to sort the collection. So there is no simple way to compare but to use equals()
Your method is just fine like this except for the other answers you got here that state that there is not overloading of operators in Java, the thing with the result = true instead of false and commenting you remember to override hashCode if you didn't already do. Let me give you one more advise. The method can be written in some more compact way:
public boolean equals(Object obj) {
if (!(obj instanceof Counter)) {
return false;
}
Counter other = (Counter) obj;
return other.min == this.min && other.max == this.max &&
other.currentCount == this.currentCount &&
other.rolloverOccurrence == this.rolloverOccurrence;
}

AssertEquals with Collections with non primitive template parameters

I have a class for a string-number pair. This class has the method compareTo implemented.
A method of another class returns a collection of elements of the pair type.
I wanted to perform a unit test on this method, and therefore wrote the following:
#Test
public void testWeight() {
Collection<StringNumber<BigDecimal>> expected = new Vector<StringNumber<BigDecimal>>();
expected.add(new StringNumber<BigDecimal>("a", BigDecimal.ONE));
expected.add(new StringNumber<BigDecimal>("b", BigDecimal.ONE));
Collection<StringNumber<BigDecimal>> actual = new Vector<StringNumber<BigDecimal>>();
expected.add(new StringNumber<BigDecimal>("a", BigDecimal.ONE));
expected.add(new StringNumber<BigDecimal>("b", BigDecimal.ONE));
//Collection<StringNumber<BigDecimal>> actual = A.f();
assertEquals(expected, actual);
}
But as you can see, the assertion fails, even though the elements in the collections are identical. What can be the reason?
The error I get is
java.lang.AssertionError: expected: java.util.Vector<[a:1, b:1]>
but was: java.util.Vector<[a:1, b:1]>
Which does not make scene to me.
Your StringNumber class requires equals() method. Then it will work. Assuming this class contains string and number fields (auto-generated by my IDE):
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof StringNumber)) {
return false;
}
StringNumber that = (StringNumber) o;
if (number != null ? !number.equals(that.number) : that.number != null) {
return false;
}
return !(string != null ? !string.equals(that.string) : that.string != null);
}
#Override
public int hashCode() {
int result = string != null ? string.hashCode() : 0;
result = 31 * result + (number != null ? number.hashCode() : 0);
return result;
}
Few remarks:
Two Vector's (why are you using such archaic data structure) are equal if:
both [...] have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).)
That's why overriding equals() is required.
when implementing equals() you must implement hashCode(). Not required here, but better be safe than sorry: What issues should be considered when overriding equals and hashCode in Java?.

how to override compareTo method

here is my compareTo method, but im still getting "missing return statement" warning.
can anyone tell me what is wrong with my code?
public int compareTo(Flows other) {
if(this.srcAddr.equals(other.srcAddr)){
if(this.dstAddr.equals(other.dstAddr)){
if(this.srcPort.equals(other.srcPort)){
if(this.dstPort.equals(other.dstPort)){
if(this.protocol.equals(other.protocol)){
return 0;
}
}
}
}
}
}
Two things:
You get the "missing return statement" because there are paths of execution where no value is returned. For example, when the first if statement computes to false.
You are breaking the compareTo() contract. For the following call: a.compareTo(b), the result should be: 0 if a equals b, <0 if a is minor than b, and >0 if a is greater than b. It seems you're using the compareTo() to check for equality, in that case the correct approach is overriding the equals() method.
This looks like an equals method. If the intention simply is to compare if the two are the same, I would do something like
return srcAddr.equals(other.srcAddr) &&
dstAddr.equals(other.dstAddr) &&
srcPort.equals(other.srcPort) &&
dstPort.equals(other.dstPort) &&
protocol.equals(other.protocol);
If it's not the intention, you're probably breaking the contract of compareTo since your method doesn't seem to adhere to the transitivity requirement. From the docs of Comparable:
The implementor must also ensure that the relation is transitive
It's because there's a possibility in your code for the compareTo to return nothing! Think about if all of those if statements fail, then it will hit the end of the method and not have returned anything. You need a return further down:
public int compareTo(Flows other) {
if(this.srcAddr.equals(other.srcAddr)){
if(this.dstAddr.equals(other.dstAddr)){
if(this.srcPort.equals(other.srcPort)){
if(this.dstPort.equals(other.dstPort)){
if(this.protocol.equals(other.protocol)){
return 0;
}
}
}
}
}
return 1;
}
Also you are not doing a complete compare. You need to return 0 if they are equal, less than 0 if the difference is less than and greater than 0 if it's greater. It seesm you'd be better off with overriding equals!
Maybe something like:
public boolean equals(Flows other) {
return (this.srcAddr.equals(other.srcAddr) && this.dstAddr.equals(other.dstAddr) && this.srcPort.equals(other.srcPort) && this.dstPort.equals(other.dstPort) && this.protocol.equals(other.protocol));
just add a "return 1" (or anything) at the end of the function, and it should solve the issue.
This will compile and run, but what about the rest of the contract? Where's less than and greater than?
public int compareTo(Flows other) {
int value = 0;
if(this.srcAddr.equals(other.srcAddr)){
if(this.dstAddr.equals(other.dstAddr)){
if(this.srcPort.equals(other.srcPort)){
if(this.dstPort.equals(other.dstPort)){
if(this.protocol.equals(other.protocol)){
value = 0;
}
}
}
}
return value;
}

Categories

Resources