overriding equal and hashcode in Java where this.obj is null - java

Hi I am trying to overriding the equal and hashcode method in for my custom class .
here is my custom class
public class property
{
public String type = null;
public int value;
public int id;
public String name = null;
public String course = null;
public property(String type, String course, int value, int id)
{
this.value = value;
this.type = type;
this.course = course;
this.id = id;
}
#Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if((obj == null) || (obj.getClass() != this.getClass()))
return false;
property sig = (property) obj;
if(sig != null) {
if(sig.type.equals("EST1")) {
if (sig.name != null && sig.type != null && sig.course != null) {
Log.d("property", "Other " + sig.course + "AHHAHAHA " + course + "shahahaaha " + sig.id + "babababaab " + id);
if (sig.course.equals(this.course) && sig.value == this.value && sig.type.equals(this.type) && sig.id == (this.id)) {
Log.d("property", "EST1");
return true;
}
}
}
return false;
}
The problem is that "this.id, this.type" is always null or 0 I do not understand why...while sig.id, sig.type have values. Just to let you know it is only code snippet, not full code so it might have typos and not logically correct..

Your code works well in my side, so I guess your test program is somewhat different (or complicated?) from mine.
I tried following for test,
property p = new property("a","b", 100, 200);
System.out.println("id:"+p.id);
System.out.println("type:"+p.type);
System.out.println(p.equals(p) +" should be true..");
And I got,
id:200
type:a
true should be true..

Related

Simplify Overridden equals and hashcode methods

I have a person class with overridden hashcode and equals, looks something like this :
class PersonKey {
private String personUID;
private String ssnUID;
private String countryCode;
public PersonKey (
String personUID, String ssnUID, String countryCode) {
this.personUID= personUID;
this.ssnUID= countryCode;
this.countryCode= countryCode;
}
.....
}
This class already had personUID and ssnUID fields and I am introducing countryCode as a new field.
This class already had a complicated hashcode and equals method, with the inclusion of countryCode the logic got even more complicated. Is there a way I can reduce the Cyclomatic Complexity using inheritance or wrapper class?
HashCode :
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result;
if (personUID != null) result += personUID.hashCode();
else result += ((ssnUID == null) ? 0 : ssnUID.hashCode());
if ((personUID != null || ssnUID != null)
&& (countryCode != null)) {
result += countryCode.hashCode();
}
return result;
}
Equals :
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PersonKey other = (PersonKey) obj;
if (!getOuterType().equals(other.getOuterType())) {
return false;
}
// For the purposes of mapping any "empty" Person (null
// personUID and ssnUID) is considered to be unique so return
// false
if ((ssnUID == null) && (personUID == null)) {
return false;
}
// Only evaluate ssnUID if the personUID is null
if (personUID == null) {
// If the current ssnUID matches the personUID
// from the other key the keys will be assumed to match
if (ssnUID.equals(other.personUID)) {
if (StringUtils.isBlank(countryCode) && StringUtils.isBlank(other.countryCode)) {
return true;
} else {
if (countryCode.equals(other.contryCode)) return true;
}
} else if (other.personUID != null) {
return false;
}
if (ssnUID.equals(other.ssnUID)) {
if (StringUtils.isBlank(v) && StringUtils.isBlank(other.countryCode)) {
return true;
} else {
if (countryCode.equals(other.countryCode)) return true;
}
}
}
// If the current personUID matches the personUID
// the keys will
// be considered a match regardless of the value of the ssnUID.
else if (personUID .equals(other.personUID)) {
if (StringUtils.isBlank(contryCode) && StringUtils.isBlank(other.contryCode)) {
return true;
} else {
if (countryCode.equals(other.countryCode)) return true;
}
}
// If the current personUID matches the ssnUID
// from the other key, and the other keys personUID is null
// the keys will be considered a match
else if ((other.personUID == null)
&& (personUID.equals(other.ssnUID))) {
if (StringUtils.isBlank(contryCode) && StringUtils.isBlank(other.contryCode)) {
return true;
} else {
if (countryCode.equals(other.countryCode)) return true;
}
}
return false;
}
You can use Lombok's #EqualsAndHashCode would be the fastest option.
Example and documentation can be found here: https://projectlombok.org/features/EqualsAndHashCode
If you create a new method in your class:
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
class PersonKey {
private String personUID;
private String ssnUID;
private String countryCode;
...
#EqualsAndHashCode.Include
public String uidOrSsn() {
return personUID != null ? personUID : ssnUID;
}
}
This way you're telling Lombok to only create the equals and hashCode for the uidOrSsn() method declared. Whichever the non-null value of personUID or ssnUID, then it will be generated.

Method that adds elements to set always throwing custom exception

Ok, so I've got a method which adds elements to a list but it is always throwing my custom exception, no matter what, even when there are no elements in the Set I made.
private Set<Plan> planSet = new HashSet<Plan>();
public Plan createPlan(String name) throws DuplicatePlan{
Plan plan = new Plan(name);
if(!planSet.contains(plan)){
planSet.add(plan);
} else {
throw(new DuplicatePlan("Error, duplicate plan"));
}
return plan;
}
I'm thinking that my equals() and hashCode() methods are causing this. Currently I'm using the default overridden Eclipse hashCode() and equals(), this is what I've got there:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj){
return true;
} if (obj == null){
return false;
} if (getClass() != obj.getClass()){
return false;
}
Plan other = (Plan) obj;
if (name == null) {
if (other.name != null){
return false;
}
} else if (!name.equals(other.name)){
return false;
}
return true;
}
This is what Plan does:
private String name;
private Set<Tables> tablesSet;
public Plan(String name){
this.name = name ;
}
Here's what's supposed to happen if a user sets the same name in the TextField:
newPlan.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent action){
if(!newPlan.getText().isEmpty()){
try {
String name = planName.getText();
plan.createPLan(name);
esquema = esquemas.createPlan(planName.getText());
optionsPlans.getItems().add(plan.getName());
} catch (DuplicatePlan e) {
dialog.errorDialog(planError, duplicate);
}
} else {
dialog.errorDialog(empty, emptySpace);
}
}
});
Had to use Answer because it was too long for comment.
This here looks suspicious to me:
String name = planName.getText();
plan.createPLan(name);
esquema = esquemas.createPlan(planName.getText());
I.e. what's up with createPLan and createPlan? Copy & paste error? Or are you calling the same method twice (which would explain the behavior)?

Provide Implementations of equals, hashCode and compareTo methods for class

I have an exam and this was in the mock and im not quite sure how to go about it, this isn't homework its simply trying to understand how to do it. Thanks.
public class Book{
private final String title;
private final String author;
private final int edition;
private Book(String title, String author, int edition)
{
this.title = title;
this.author = author;
this.edition = edition;
}
public String getTitle()
{
return title;
}
public String getAuthor()
{
return author;
}
public String getEdition()
{
return edition;
}
}
I need to provide implementations of equals, hashCode and compareTo methods for the above code.
I'm not to sure how to go about it, would it be somthing similar to this for the compareTo method?
title.compareTo(title);
author.compareTo(author);
edition.compareTo(edition);
Thanks, any help would be greatly appreciated.
your compareTo should be this:
title.compareToIgnoreCase(otherTitle);
...
equals:
if(null == title || null == author || null == editor)
{
return false;
}
if(!title.equals(otherTitle)
{
return false;
}
if(!author.equals(otherAuthor)
{
return false;
}
if(!editor.equals(otherEditor)
{
return false;
}
return true;
Take look at this.
http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/package-summary.html
You can use the builders in this package to create default implementations.
IDEs like Eclipse can generate hashCode and equals methods for you (Source -> generate hashCode() and equals()). You can even specify which fields of the object need to match for it to be considered "equal".
For instance here is what Eclipse generates for your class:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((author == null) ? 0 : author.hashCode());
result = prime * result + edition;
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (author == null) {
if (other.author != null)
return false;
} else if (!author.equals(other.author))
return false;
if (edition != other.edition)
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}

Check object empty

Basically how do you check if an object is null or empty. What I mean is that if I have an object instantiated but all its values or fields are null, the how do I check in code if it is empty?
I have tried;
if (doc != null){
.... do something
But it doesn't seem to work.
You can't do it directly, you should provide your own way to check this. Eg.
class MyClass {
Object attr1, attr2, attr3;
public boolean isValid() {
return attr1 != null && attr2 != null && attr3 != null;
}
}
Or make all fields final and initialize them in constructors so that you can be sure that everything is initialized.
import org.apache.commons.lang3.ObjectUtils;
if(ObjectUtils.isEmpty(yourObject)){
//your block here
}
This can be done with java reflection,This method returns false if any one attribute value is present for the object ,hope it helps some one
public boolean isEmpty() {
for (Field field : this.getClass().getDeclaredFields()) {
try {
field.setAccessible(true);
if (field.get(this)!=null) {
return false;
}
} catch (Exception e) {
System.out.println("Exception occured in processing");
}
}
return true;
}
You should check it against null.
If you want to check if object x is null or not, you can do:
if(x != null)
But if it is not null, it can have properties which are null or empty. You will check those explicitly:
if(x.getProperty() != null)
For "empty" check, it depends on what type is involved. For a Java String, you usually do:
if(str != null && !str.isEmpty())
As you haven't mentioned about any specific problem with this, difficult to tell.
I suggest you add separate overloaded method and add them to your projects Utility/Utilities class.
To check for Collection be empty or null
public static boolean isEmpty(Collection obj) {
return obj == null || obj.isEmpty();
}
or use Apache Commons CollectionUtils.isEmpty()
To check if Map is empty or null
public static boolean isEmpty(Map<?, ?> value) {
return value == null || value.isEmpty();
}
or use Apache Commons MapUtils.isEmpty()
To check for String empty or null
public static boolean isEmpty(String string) {
return string == null || string.trim().isEmpty();
}
or use Apache Commons StringUtils.isBlank()
To check an object is null is easy but to verify if it's empty is tricky as object can have many private or inherited variables and nested objects which should all be empty. For that All need to be verified or some isEmpty() method be in all objects which would verify the objects emptiness.
If your Object contains Objects then check if they are null, if it have primitives check for their default values.
for Instance:
Person Object
name Property with getter and setter
to check if name is not initialized.
Person p = new Person();
if(p.getName()!=null)
I have a way, you guys tell me how good it is.
Create a new object of the class and compare it with your object (which you want to check for emptiness).
To be correctly able to do it :
Override the hashCode() and equals() methods of your model class and also of the classes, objects of whose are members of your class, for example :
Person class (primary model class) :
public class Person {
private int age;
private String firstName;
private String lastName;
private Address address;
//getters and setters
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + age;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (age != other.age)
return false;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
#Override
public String toString() {
return "Person [age=" + age + ", firstName=" + firstName + ", lastName=" + lastName + ", address=" + address
+ "]";
}
}
Address class (used inside Person class) :
public class Address {
private String line1;
private String line2;
//getters and setters
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((line1 == null) ? 0 : line1.hashCode());
result = prime * result + ((line2 == null) ? 0 : line2.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Address other = (Address) obj;
if (line1 == null) {
if (other.line1 != null)
return false;
} else if (!line1.equals(other.line1))
return false;
if (line2 == null) {
if (other.line2 != null)
return false;
} else if (!line2.equals(other.line2))
return false;
return true;
}
#Override
public String toString() {
return "Address [line1=" + line1 + ", line2=" + line2 + "]";
}
}
Now in the main class :
Person person1 = new Person();
person1.setAge(20);
Person person2 = new Person();
Person person3 = new Person();
if(person1.equals(person2)) --> this will be false
if(person2.equals(person3)) --> this will be true
I hope this is the best way instead of putting if conditions on each and every member variables.
Let me know !
for simple (It's worked in my project).
if null check not mandatory for some fields then exclude it from toString() method as in my above code, I have removed school.
public class Student {
private String name;
private String school;
private Integer roll;
private String section;
//getters and setters
#Override
public String toString() {
return "Student [name=" + name + ", roll=" + roll + ", section=" + section + "]";
}
}
public class StudentRunner {
public static void main(String[] args) {
Student s = new Student();
s.setName("ved");
s.setRoll(12);
s.setSection("A");
s.setSchool(null);//school set null and it removed from toString() method
if(s.toString().contains("null")) {
System.out.println("null value contains");
//do your work here or throw exception
} else {
System.out.println("no null value");
}
}
}
output : no null value
let suppose ,
data = {};
if( if(!$.isEmptyObject(data)))
{
document.write("Object is empty);
}
else{
document.write("Object is not empty);
}
It worked for me and its an easy way to check if object is empty or not

How to sort an ArrayList using multiple sorting criteria?

I have an array list that contains Quote objects. I want to be able to sort alphabetically by name, by change, and by percent change. How can I sort my arraylist?
package org.stocktwits.model;
import java.io.Serializable;
import java.text.DecimalFormat;
public class Quote implements Serializable {
private static final long serialVersionUID = 1L;
public String symbol;
public String name;
public String change;
public String percentChange;
public String open;
public String daysHigh;
public String daysLow;
public String dividendYield;
public String volume;
public String averageDailyVolume;
public String peRatio;
public String marketCapitalization;
public String yearHigh;
public String yearLow;
public String lastTradePriceOnly;
public DecimalFormat df = new DecimalFormat("#,###,###,###,###,##0.00");
public DecimalFormat vf = new DecimalFormat("#,###,###,###,###,##0");
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getChange() {
return change;
}
public void setChange(String change) {
if(change.equals("null")){
this.change = "N/A";
}
else{
float floatedChange = Float.valueOf(change);
this.change = (df.format(floatedChange));
}
}
public String getPercentChange() {
return percentChange;
}
public void setPercentChange(String percentChange) {
if(percentChange.equals("null"))
percentChange = "N/A";
else
this.percentChange = percentChange;
}
public String getOpen() {
return open;
}
public void setOpen(String open) {
if(open.equals("null"))
this.open = "N/A";
else
this.open = open;
}
public String getDaysHigh() {
return daysHigh;
}
public void setDaysHigh(String daysHigh) {
if(daysHigh.equals("null"))
this.daysHigh = "N/A";
else{
float floatedDaysHigh = Float.valueOf(daysHigh);
this.daysHigh = (df.format(floatedDaysHigh));
}
}
public String getDaysLow() {
return daysLow;
}
public void setDaysLow(String daysLow) {
if(daysLow.equals("null"))
this.daysLow = "N/A";
else{
float floatedDaysLow = Float.valueOf(daysLow);
this.daysLow = (df.format(floatedDaysLow));
}
}
public String getVolume() {
return volume;
}
public void setVolume(String volume) {
if(volume.equals("null")){
this.volume = "N/A";
}
else{
float floatedVolume = Float.valueOf(volume);
this.volume = (vf.format(floatedVolume));
}
}
public String getDividendYield() {
return dividendYield;
}
public void setDividendYield(String dividendYield) {
if(dividendYield.equals("null"))
this.dividendYield = "N/A";
else
this.dividendYield = dividendYield;
}
public String getAverageDailyVolume() {
return averageDailyVolume;
}
public void setAverageDailyVolume(String averageDailyVolume) {
if(averageDailyVolume.equals("null")){
this.averageDailyVolume = "N/A";
}
else{
float floatedAverageDailyVolume = Float.valueOf(averageDailyVolume);
this.averageDailyVolume = (vf.format(floatedAverageDailyVolume));
}
}
public String getPeRatio() {
return peRatio;
}
public void setPeRatio(String peRatio) {
if(peRatio.equals("null"))
this.peRatio = "N/A";
else
this.peRatio = peRatio;
}
public String getMarketCapitalization() {
return marketCapitalization;
}
public void setMarketCapitalization(String marketCapitalization) {
if(marketCapitalization.equals("null"))
this.marketCapitalization = "N/A";
else
this.marketCapitalization = marketCapitalization;
}
public String getYearHigh() {
return yearHigh;
}
public void setYearHigh(String yearHigh) {
if(yearHigh.equals("null"))
this.yearHigh = "N/A";
else
this.yearHigh = yearHigh;
}
public String getYearLow() {
return yearLow;
}
public void setYearLow(String yearLow) {
if(yearLow.equals("null"))
this.yearLow = "N/A";
else
this.yearLow = yearLow;
}
public String getLastTradePriceOnly() {
return lastTradePriceOnly;
}
public void setLastTradePriceOnly(String lastTradePriceOnly) {
if(lastTradePriceOnly.equals("null")){
this.lastTradePriceOnly = "N/A";
}
else{
float floatedLastTradePriceOnly = Float.valueOf(lastTradePriceOnly);
this.lastTradePriceOnly = (df.format(floatedLastTradePriceOnly));
}
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((change == null) ? 0 : change.hashCode());
result = prime * result
+ ((daysHigh == null) ? 0 : daysHigh.hashCode());
result = prime * result + ((daysLow == null) ? 0 : daysLow.hashCode());
result = prime
* result
+ ((lastTradePriceOnly == null) ? 0 : lastTradePriceOnly
.hashCode());
result = prime
* result
+ ((marketCapitalization == null) ? 0 : marketCapitalization
.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((open == null) ? 0 : open.hashCode());
result = prime * result + ((peRatio == null) ? 0 : peRatio.hashCode());
result = prime * result
+ ((percentChange == null) ? 0 : percentChange.hashCode());
result = prime * result + ((symbol == null) ? 0 : symbol.hashCode());
result = prime * result + ((volume == null) ? 0 : volume.hashCode());
result = prime * result
+ ((yearHigh == null) ? 0 : yearHigh.hashCode());
result = prime * result + ((yearLow == null) ? 0 : yearLow.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Quote other = (Quote) obj;
if (change == null) {
if (other.change != null)
return false;
} else if (!change.equals(other.change))
return false;
if (daysHigh == null) {
if (other.daysHigh != null)
return false;
} else if (!daysHigh.equals(other.daysHigh))
return false;
if (daysLow == null) {
if (other.daysLow != null)
return false;
} else if (!daysLow.equals(other.daysLow))
return false;
if (lastTradePriceOnly == null) {
if (other.lastTradePriceOnly != null)
return false;
} else if (!lastTradePriceOnly.equals(other.lastTradePriceOnly))
return false;
if (marketCapitalization == null) {
if (other.marketCapitalization != null)
return false;
} else if (!marketCapitalization.equals(other.marketCapitalization))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (open == null) {
if (other.open != null)
return false;
} else if (!open.equals(other.open))
return false;
if (peRatio == null) {
if (other.peRatio != null)
return false;
} else if (!peRatio.equals(other.peRatio))
return false;
if (percentChange == null) {
if (other.percentChange != null)
return false;
} else if (!percentChange.equals(other.percentChange))
return false;
if (symbol == null) {
if (other.symbol != null)
return false;
} else if (!symbol.equals(other.symbol))
return false;
if (volume == null) {
if (other.volume != null)
return false;
} else if (!volume.equals(other.volume))
return false;
if (yearHigh == null) {
if (other.yearHigh != null)
return false;
} else if (!yearHigh.equals(other.yearHigh))
return false;
if (yearLow == null) {
if (other.yearLow != null)
return false;
} else if (!yearLow.equals(other.yearLow))
return false;
return true;
}
}
If you (almost) always want to use that order you can add the Comparable interface to Quote and implement a compareTo method.
public int compareTo(Quote quote) {
int result = this.getName().compareTo(quote.getName());
if (result == 0) {
result = this.getChange().compareTo(quote.getChange());
}
if (result == 0) {
result = this.getPercentChange().compareTo(quote.getPercentChange());
}
return result;
}
Then use a sorted collection, or sort a list, and the quotes will be sorted.
For ad hoc sorting, a separate, possibly anonymous, Comparator is better.
Everybody is right that you want to use Comparators. Extending on that idea, if you want to be able to sort on multiple criteria, then a class like this will work for you:
public class MultiComparator<T> implements Comparator<T> {
private List<Comparator<T>> comparators;
public MultiComparator(List<Comparator<T>> comparators) {
this.comparators = comparators;
}
public int compare(T o1, T o2) {
for (Comparator<T> comparator : comparators) {
int comparison = comparator.compare(o1, o2);
if (comparison != 0) return comparison;
}
return 0;
}
}
Then you just write really simple comparators for whichever fields you desire and you can combine them into more complex comparators more easily and with more reuse.
Have a look at the ComparatorChain from the Apache Commons Collection. This should do the job. Don't implement logic if is already available and tested.
At the following site I have a tutorial: Sorting Objects By Multiple Attributes"
Create an appropiate Comparator that will compare two items according to your desired criteria. Then use Collections.sort() on your ArrayList.
If at a later time you want to sort by different criteria, call Collections.sort() again with a different Comparator.
Sun has devoted big part of its tutorial to sorting in Java collections:
http://download.oracle.com/javase/tutorial/collections/interfaces/order.html
It discusses both Comparable and Comparator interfaces with examples.
See Collections.sort with an explicit Comparator (or the Collections.sort kind that requires the input to implement Comparable, if you prefer).
There are two things:
Sorting on multiple fields of an object
Multilevel sorting (Here sorting done on first field and then next sorting applied on grouping done on similar items in previous sort)
For #2: I found this below article very much close to what i desire
http://strangeoptics.blogspot.com/2011/09/sorting-objects-by-multiple-attributes.html

Categories

Resources