I need to write abstract class, which looks like this.
public abstract class Value {
public abstract String toString();
public abstract Value add(Value v);
public abstract Value sub(Value v);
public abstract boolean eq(Value v);
public abstract boolean lte(Value v);
public abstract boolean gte(Value v);
public abstract boolean neq(Value v);
public abstract boolean equals(Object other);
public abstract int hashCode();
public abstract Value create(String s);
}
Now I need to make few classe, which inherit from that one. I started from Int class and implemented it like this:
public class Int extends Value {
int val;
public String toString() {
String toStr = Integer.toString(val);
return toStr;
}
public Int add(Value v) {
Int result = new Int();
if(v instanceof Int) {
Int temp = (Int) v;
result.val = val + temp.val;
}
return result;
}
public Int sub(Value v) {
Int result = new Int();
if(v instanceof Int) {
Int temp = (Int) v;
result.val = val - temp.val;
}
return result;
}
public boolean eq(Value o) {
if(this == o) return true;
if(this == null) return false;
if(getClass() != o.getClass()) return false;
Int other = (Int) o;
return toString() == other.toString();
}
public boolean lte(Value v) {
if(v instanceof Int) {
Int temp = (Int) v;
return this.val < temp.val;
}
return false;
}
public boolean gte(Value v) {
if(v instanceof Int) {
Int temp = (Int) v;
return this.val > temp.val;
}
return false;
}
public boolean neq(Value v) {
if(v instanceof Int) {
Int temp = (Int) v;
return !eq(temp);
}
return true;
}
public boolean equals(Object o) {
if(this == o) return true;
if(this == null) return false;
if(getClass() != o.getClass()) return false;
Int other = (Int) o;
return toString() == other.toString();
}
public int hashCode() {
Integer hash = val;
return hash.hashCode();
}
public Int create(String s) {
val = Integer.parseInt(s);
return this;
}
}
Everything is compiling and working, but I have no clue if my hashcode() function and equals() are good. Furthermore i want to use create() to make objects like this:
getInstance().create("1234");
Is my method also sufficient?
Everything is compiling and working, but I have no clue if my hashcode() function and equals() are good.
Your equals() should compare int val and not result of toString() of compared objects (this.val == other.val).
Your hashCode() looks good, though I would add #Override to it (same with equals()).
Furthermore i want to use create() to make objects like this: getInstance().create("1234");
Looking at its implementation, it looks fine (i.e. would work according to your needs):
public Int create(String s) {
val = Integer.parseInt(s);
return this;
}
though I don't think you really want to use it with getInstance(). Simply Int.create() would be enough:
public static Int create(String s) {
val = Integer.parseInt(s);
return new Int(val);
}
Note that you would need a private constructor.
Also, as someone noted in the comments, consider using generics instead of inheritance.
The hashCode() method is fine (although I'd add an #Override annotation, just to make the code easier to maintain and avoid mistakes), but the equals(Object) definitely isn't.
Following the logic you have in place, == isn't the right way to compare strings. You should use equals instead (see, e.g., How do I compare strings in Java?). In addition, as Joakim Danielson noted in the comments, this can never be null - you should check if o is null instead:
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if(getClass() != o.getClass()) {
return false;
}
Int other = (Int) o;
return toString().equals(other.toString()); // Here!
}
But in all fairness, there's no reason to use toString - you could just compare the internal val:
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if(getClass() != o.getClass()) {
return false;
}
Int other = (Int) o;
return val == other.val; // Here!
}
First when you override Methods please do it with #Override Annotation. Then i would implement your equals method in another way. Just do return this.val == other.val instead of doing this.toString() == other.toString(). Your toString() method implementation is ok. Your hashCode is good as well. But please remove that create method. Use a constructor instead.
Can I implement equals() method using eq() like this ?
public boolean equals(Object o) {
Value compare = (Value) o;
return eq(compare);
}
Related
I'm trying to make a generic tuple class. It stores its elements as an ArrayList. Of course, this class should override hashcode and equals methods.
How could I make hashcode method for this class? You see, in the code, I am having trouble.
Also, for the equals method, why does the compiler force me to use the '?'. Why couldn't I just use the T?
public static class Tuple<T> {
ArrayList<T> tuple = new ArrayList<>();
public Tuple(ArrayList<T> items) {
for (T item : items) {
tuple.add(item);
}
}
#Override
public int hashCode() {
T sum = ???;
for (T item : tuple) {
sum += item.hashCode();
}
return sum;
}
#Override
public boolean equals(Object o) {
if (o instanceof Tuple<?>) {
Tuple<?> tup= (Tuple<?>) o;
if (tup.tuple.size() != this.tuple.size()) {
return false;
}
for (int i = 0; i < this.tuple.size(); i++) {
if (this.tuple.get(i) != tup.tuple.get(i)) {
return false;
}
}
return true;
} else {
return false;
}
}
}
As mentioned in the comments, we should delegate the hashCode and the equals methods to the ArrayList<T> tuple instance variable. For the hashCode it's trivial. For the equals it's just a little more complicated than that because we don't want our custom Tuple to be equals with an ArrayList. So here it is:
public class Tuple<T> {
// I made this private because I'm pedantric ;)
private final ArrayList<T> tuple = new ArrayList<>();
// this does the same as your code, it's just easier to read
public Tuple(ArrayList<T> items) {
tuple.addAll(items);
}
#Override
public int hashCode() {
return tuple.hashCode();
}
// generated by eclipse
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Tuple other = (Tuple) obj;
if (tuple == null) {
if (other.tuple != null)
return false;
} else if (!tuple.equals(other.tuple))
return false;
return true;
}
}
If you want to deal with the case when the tuple can be null, then you can use a slightly more complex hashCode:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((tuple == null) ? 0 : tuple.hashCode());
return tuple.hashCode();
}
In general, I don't like to write these methods myself. Usually, I make my IDE to generate the stuff. All I need to take care of is to re-generate it when I add new fields. Apache HashCodeBuilder and EqualsBuilder are also great alternatives.
#IdClass=(value = TripleKey.class)
class Triple {
String subject;
String predicate;
String object;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
Triple triple = (Triple) o;
if (!subject.equals(triple.subject)) return false;
return predicate.equals(triple.predicate);
}
#Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + subject.hashCode();
result = 31 * result + predicate.hashCode();
return result;
}
}
my objects are:
{
"subject": "http://www.someurl.com/thing/resources/<owner>#SenMLJSON",
"predicate": "probes_in",
"object":"http://sweet.jpl.nasa.gov/2.3/matrSediment.owl#clay"
}
and
{
"subject": "http://www.someurl.com/thing/resources/<owner>#SenMLJSON",
"predicate": "probes_in",
"object":"http://sweet.jpl.nasa.gov/2.3/matrSediment.owl#sand"
}
When I try the following I still have duplicates :
public static List<Triple> mergeTripleLists(List<Triple> oldList, List<Triple> newList) {
Set<Triple> tripleSet = new HashSet<>(oldList);
tripleSet.removeAll(newList);
tripleSet.addAll(newList);
return new ArrayList<>(tripleSet);
}
The problem is in:
if (!super.equals(o)) return false;
If should work after removing it.
The problem is the call to the equals method of the super class which uses object reference to test equality, so remove the line with
!super.equals(o)
You also need to remove the call to the hashCode method of the super class.
I am writing a comparable class. I have overridden compareTo method to sort my objects based on date in descending order.
public class Employee implements Comparable
{
private Timestamp joinDate;
public Timestamp getJoinDate()
{
return joinDate;
}
public void setJoinDate(Timestamp joinDate)
{
this.joinDate = joinDate;
}
#Override
public int compareTo(Employee a)
{
//sort employess based on join date desc
return a.getJoinDate().compareTo(this.getJoinDate());
}
}
My Sonar is complaing to override equals method.
How do I override equals method here.
If you want to override the method compareTo, you have to use the same signature. The actual signature uses an Object parameter:
#Override
public int compareTo(Object o)
{
return ((Employee) o).getJoinDate().compareTo(joinDate);
}
Note that you have to explicitly cast the object obj to Employee, otherwise you won't be able to call its method getJoinDate().
Edit: If you want to override the equals() method you can return the result of comparing the attributes joinDate:
#Override
public boolean equals(Object obj)
{
return joinDate.equals(((Employee) obj).getJoinDate());
}
Note: It's not necessary to call getJoinDate() inside the Employee class, so you can just do:
return ((Employee) o).joinDate.compareTo(joinDate);
or
return joinDate.equals(((Employee) obj).joinDate);
Include this on your class (when you override equals, you have to also override hashCode):
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((joinDate == null) ? 0 : joinDate.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;
Snippet other = (Snippet) obj;
if (joinDate == null) {
if (other.joinDate != null)
return false;
} else if (!joinDate.equals(other.joinDate))
return false;
return true;
}
There is a difference between what what is indicated by .equals() == true and .compareTo(...) == 0. equals() method is intended to check whether two objects are equal, while compareTo is intended to set a relation order between elements, whether one is greater then the other, other is greater then the first one, or none of this is applicable which is typically means that objects are equal.
Unless you have a very good reason, you should override both equals and compareTo. An example of very good reason is BigDecimal class where equals compares both value of the object and its scale, while compareTo compares only values.
For your case, I'd override equals() like this:
#Override
public int hashCode() {
return this.getJoinDate().hashCode();
}
#Override
public boolean equals(Object obj) {
//correct argument check
if (!(obj instanceof Employee)) {
return false;
}
//check nulls
if (obj == null) {
return false;
}
Employee other = (Employee) obj;
if (this.getJoinDate() == null) {
return other.getJoinDate() == null;
}
return this.getJoinDate().equals(other.getJoinDate());
}
What is the correct way to compare two Pair<?,?> ?
I use this code, but I'm not 100% sure about it?
May be you know another better solution?
public boolean equals(Object other) {
if (other instanceof Pair<?,?>) {
Pair<?, ?> otherPair = (Pair<?, ?>) other;
return equalsPart(this._first, otherPair._first) && equalsPart(this._second, otherPair._second);
}
return false;
}
public boolean equalsPart(Class<?> one, Class<?> two) {
return ((one== two || (one!= null && two != null && one.equals(two))));
}
public boolean equals(Object other) {
if(this == other)
return true;
if (!(other instanceof Pair)) {
return false;
}
Pair<?, ?> otherPair = (Pair<?, ?>) other;
return Equality.equals(this.first,otherPair._first) &&
Equality.equals(this._second, otherPair._second);
}
class Equality{
public static boolean equals(Object first, Object second){
return first == null ? second == null : first.equals(second);
}
}
You will find this kind of idiom being followed in many libraries for equals(). A precondition check and a fail fast approach to equals().
Have created a new Utility Equality for use in further classes which improves readability as well as provides proper null checking.
I believe the following is an accurate solution to this. Since neither Java nor the OP provide a definition for Pair<?, ?>, I have included the complete definition for the class I actually use below. The code includes a definition of hashCode for completeness.
public class Tuple2<T1, T2> {
private final T1 item1;
private final T2 item2;
public Tuple2(T1 item1, T2 item2) {
this.item1 = item1;
this.item2 = item2;
}
public final T1 getItem1() {
return item1;
}
public final T2 getItem2() {
return item2;
}
#Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
else if (!(obj instanceof Tuple2<?, ?>)) {
return false;
}
Tuple2<?, ?> other = (Tuple2<?, ?>)obj;
return Tuple.equals(this.item1, other.item1)
&& Tuple.equals(this.item2, other.item2);
}
#Override
public int hashCode() {
int hash = 5;
hash = 79 * hash + (this.item1 != null ? this.item1.hashCode() : 0);
hash = 79 * hash + (this.item2 != null ? this.item2.hashCode() : 0);
return hash;
}
}
I have a set of this structure. How to remove duplicates of equal object of that class? Equals means field File plik is the same.
EDIT:
But the problem gut bigger I don't have duplicates but I would like to replace old SET member by new.
Withoud 3rd party libraries.
import java.io.*;
public class WordInfo implements Serializable {
File plik;
Integer wystapienia;
public WordInfo(File plik, Integer wystapienia) {
this.plik = plik;
this.wystapienia = wystapienia;
}
public String toString() {
// if (plik.getAbsolutePath().contains("src") && wystapienia != 0)
return plik.getAbsolutePath() + "\tWYSTAPIEN " + wystapienia;
// return "";
}
}
EDIT
I don't have this HashCodeBuilder I want to use Java standard libraries
public int hashCode() {
return new HashCodeBuilder(17, 31).append(plik).append(wystapienia).toHashCode();
}
public boolean equals(Object obj) {
File f = (File) obj;
return(plik.getAbsoluteFile().equals(f.getAbsolutePath()));
}
As discussed here, override equals.
public class Person {
private String name;
private int age;
// ...
public int hashCode() {
return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
// if deriving: appendSuper(super.hashCode()).
append(name).
append(age).
toHashCode();
}
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (obj.getClass() != getClass())
return false;
Person rhs = (Person) obj;
return new EqualsBuilder().
// if deriving: appendSuper(super.equals(obj)).
append(name, rhs.name).
append(age, rhs.age).
isEquals();
}
}
public class WordInfo implements Serializable {
File plik;
Considering that following is how you can override the equals and hashCode method as per your requirement:
#Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(!(obj instanceof WordInfo)) return false;
return this.plik.equals(((WordInfo) obj).plik);
}
#Override
public int hashCode() {
return this.plik.hashCode();
}