Implements Comparable to get alphabetical sort with Strings - java

I would like an object to be comparable (to use it in a TreeSet in that case).
My object got a name field and I would like it to be sorted by alphabetical order.
I thought first that I could use the unicode value of the string and simply do a subtraction, but then AA would be after Ab for example…
Here’s how I started :
public final class MyObject implements Comparable<MyObject> {
private String name;
public MyObject(String name) {
this.name = name;
}
public String name() {
return name;
}
#Override
public int compareTo(MyObject otherObject) {
return WHAT DO I PUT HERE ?;
}
}
Thanks to those who will help,
have a nice day!

You are overthinking the problem. Strings have their own natural ordering, which is alphabetic, so you can just use the String.compareTo like this:
#Override
public int compareTo(MyObject otherObject) {
return this.name.compareTo(otherObject.name);
}

return name.compareTo(otherObject.name);
String already implements Comparable so you don't need do to anything.

I think you want something like this
package mine;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MyObject {
private String name;
public MyObject(String name) {
this.name = name;
}
public MyObject() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "MyObject [name=" + name + "]";
}
public static void main(String[] args){
List<MyObject> l = new ArrayList<>();
l.add(new MyObject("Ab"));
l.add(new MyObject("AA"));
l.add(new MyObject());
Collections.sort(l, new Comparator<MyObject>(){
#Override
public int compare(MyObject o1, MyObject o2) {
if (o1.name == null && o2.name == null){
return 0;
}else if (o1.name == null){
return -1;
}else if (o2.name == null){
return 1;
}else{
return o1.name.toUpperCase().compareTo(o2.name.toUpperCase());
}
}
});
System.out.println(l);
}
}

Exist so many way which preferred before it. But for maintain better compatibility, performance and avoiding runtime exceptions (such as NullPointerException) use best practices which is
For String
#Override
public int compareTo(OtherObject o) {
return String.CASE_INSENSITIVE_ORDER.compare(this.name,o.name);
}
For int, double float (to avoid boxing and unboxing which issue for performance use below comparators)
// with functional expression
Comparator.compareInt, Comparator.compareDouble, Comparator.compareFloat
// or with static compare method
/**
* Integer
*/
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
/**
* Double
*/
public int compareTo(Double anotherDouble) {
return Double.compare(value, anotherDouble.value);
}
/**
* Float
*/
public int compareTo(Float anotherFloat) {
return Float.compare(value, anotherFloat.value);
}
/**
* Objects
*/
public int compareTo(Object other) {
return Object.compare(value, other.value);
}
[Effective Java Item 14: Consider implement Comparable]
Finally, whenever you implement a value class that has a sensible ordering, you should have a class implements Comparable interface so that its instances can be easily sorted, searched and used in comparison-based collections. When comparing field values in the implementations of the compareTo methods, avoid the use of the < and > operators. Instead, use the static compare methods in the boxed primitive classes or the comparator construction methods in the Comparator interface

Related

Using comparator with multiple comparators

I can use all the simple comparators in this code for sorting just fine but not the ComplexComparator. I couldn't figure it out how to code to get it to work properly. Any suggestion / explanation would be appreciated.
This is my main program:
package pkgTest;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Student[] students = new Student[6];
students[0] = new Student("Pete", 1989, 3.6);
students[1] = new Student("Tomas", 1989, 3.9);
students[2] = new Student("Helen", 1990, 3.6);
students[3] = new Student("Steve", 1991, 3.7);
students[4] = new Student("Natalie", 1993, 3.7);
students[5] = new Student("John", 1992, 4.0);
NameComparator byName
= new NameComparator();
BirthDateComparator byBirthDate
= new BirthDateComparator();
AverageComparator byAverage
= new AverageComparator();
ComplexComparator complexSorting
= new ComplexComparator(byName,
byAverage);
System.out.println("===============");
System.out.println("Before sorting:");
System.out.println("===============");
for (Student student : students) {
System.out.println(student.getName()
+ " // " + student.getBirthDate()
+ " // " + student.getAverage());
}
Arrays.sort(students, complexSorting);
System.out.println("==============");
System.out.println("After sorting:");
System.out.println("==============");
for (Student student : students) {
System.out.println(student.getName()
+ " // " + student.getBirthDate()
+ " // " + student.getAverage());
}
}
}
Here are the rest of the classes:
package pkgTest;
public class Student {
private String name;
private int birthDate;
private double average;
public Student(String name, int birthDate,
double average) {
this.name = name;
this.birthDate = birthDate;
this.average = average;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getBirthDate() {
return this.birthDate;
}
public void setBirthDate(int birthDate) {
this.birthDate = birthDate;
}
public double getAverage() {
return this.average;
}
public void setAverage(double average) {
this.average = average;
}
}
package pkgTest;
import java.util.Comparator;
public class ComplexComparator implements Comparator<Student> {
public ComplexComparator(Comparator<Student> one,
Comparator<Student> another) {
}
#Override
public int compare(Student one, Student another) {
/*This is the part that
I just couldn't figure
it out to get it work.
It has to work no matter
which 2 of the 3 comparators
I use to set the input
parameters of ComplexComparator.
I have to make it work by
modifying only this part of
the code.*/
}
}
package pkgTest;
import java.util.Comparator;
public class AverageComparator implements Comparator<Student> {
#Override
public int compare(Student one, Student another) {
if (one.getAverage()
< another.getAverage()) {
return -1;
} else if (one.getAverage()
== another.getAverage()) {
return 0;
} else {
return +1;
}
}
}
package pkgTest;
import java.util.Comparator;
public class BirthDateComparator implements Comparator<Student> {
#Override
public int compare(Student one, Student another) {
if (one.getBirthDate()
< another.getBirthDate()) {
return -1;
} else if (one.getBirthDate()
== another.getBirthDate()) {
return 0;
} else {
return +1;
}
}
}
package pkgTest;
import java.util.Comparator;
public class NameComparator implements Comparator<Student> {
#Override
public int compare(Student one, Student another) {
return one.getName().
compareToIgnoreCase(another.getName());
}
}
You will have to modify the class ComplexComparator like the following, at least...
import java.util.Comparator;
public class ComplexComparator implements Comparator<Student> {
private Comparator<Student> comparatorOne;
private Comparator<Student> comparatorTwo;
public ComplexComparator(Comparator<Student> one,
Comparator<Student> another) {
this.comparatorOne = one;
this.comparatorTwo = another;
}
#Override
public int compare(Student one, Student another) {
// make a first comparison using comparator one
int comparisonByOne = comparatorOne.compare(one, another);
// check if it was 0 (items equal in that attribute)
if (comparisonByOne == 0) {
// if yes, return the result of the next comparison
return comparatorTwo.compare(one, another);
} else {
// otherwise return the result of the first comparison
return comparisonByOne;
}
}
}
For more than two Comparators you will need a List of them (or another overloaded constructor) and a loop that keeps a certain order of comparisons.
EDIT
For your additional requirement regarding sorting orders, this may be helpful:
public class ComplexComparator implements Comparator<Student> {
private Comparator<Student> comparatorOne;
private Comparator<Student> comparatorTwo;
private boolean orderOneAscending = true;
private boolean orderTwoAscending = true;
/**
* Constructor without any sort orders
* #param one a comparator
* #param another another comparator
*/
public ComplexComparator(Comparator<Student> one, Comparator<Student> another) {
this.comparatorOne = one;
this.comparatorTwo = another;
}
/**
* Constructor that provides the possibility of setting sort orders
* #param one a comparator
* #param orderOneAscending sort order for comparator one
* (true = ascending, false = descending)
* #param another another comparator
* #param orderTwoAscending sort order for comparator two
* (true = ascending, false = descending)
*/
public ComplexComparator(Comparator<Student> one, boolean orderOneAscending,
Comparator<Student> another, boolean orderTwoAscending) {
this.comparatorOne = one;
this.comparatorTwo = another;
this.orderOneAscending = orderOneAscending;
this.orderTwoAscending = orderTwoAscending;
}
#Override
public int compare(Student one, Student another) {
int comparisonByOne;
int comparisonByAnother;
if (orderOneAscending) {
/* note that your lexicographical comparison in NameComparator
returns a negative integer if the String is greater!
If you take two numerical Comparators, the order will
turn into the opposite direction! */
comparisonByOne = comparatorOne.compare(another, one);
} else {
comparisonByOne = comparatorOne.compare(one, another);
}
if (orderTwoAscending) {
comparisonByAnother = comparatorTwo.compare(one, another);
} else {
comparisonByAnother = comparatorTwo.compare(another, one);
}
if (comparisonByOne == 0) {
return comparisonByAnother;
} else {
return comparisonByOne;
}
}
}
Just play around with the values and try some modifications to get familiar with common problems concerning comparing and sorting.
I hope this will be helpful...
Modify Your ComplexComparator as below
public class ComplexComparator implements Comparator<Student> {
private List<Comparator<Student>> listComparators;
#SafeVarargs
public ComplexComparator(Comparator<Student>... comparators) {
this.listComparators = Arrays.asList(comparators);
}
#Override
public int compare(Student studen1, Student studen2) {
for (Comparator<Student> comparator : listComparators) {
int result = comparator.compare(studen1, studen2);
if (result != 0) {
return result;
}
}
return 0;
}
}
Here is a generic complex comparator you can use for any type of of objects (based on this answer):
public class ComplexComparator<T> implements Comparator<T> {
private List<Comparator<T>> listComparators;
#SafeVarargs
public ComplexComparator(Comparator<T>... comparators) {
listComparators = Arrays.asList(comparators);
}
#Override
public int compare(T o1, T o2) {
for (Comparator<T> comparator : listComparators) {
int result = comparator.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
}
There will be an unchecked cast warning when you use it, but you can suppress that, given that it will cast successfully as long as your class is comparable.
#SuppressWarnings("unchecked")
Comparator<MyClass> comparator = new ComplexComparator(
MyClass.ComparatorA,
MyClass.ComparatorB);
Collections.sort(mySet, comparator);
If anyone knows a way how to not get that warning, please comment and I update the answer.
I am not sure exactly how you want the solution to be presented. But from my understanding, if you want to do it by just putting code in the commented place, you can just try putting code like this.
Assuming the case when after comparing name, if same, you intend to move to average.
public int compare(Student StOne, Student StAnother) {
if(one.compare(Sone, Sanother)==0) {
return another.compare(StOne, StAnother);
}
else
return one.compare(StOne, StAnother);
}
But for this, you need to ensure that the values you take in the constructor of ComplexComparator (byName, byAverage) should be the instance variables of the class, and need to be initialized in the constructor.
public class ComplexComparator implements Comparator<Student> {
private Comparator<Student> one;
private Comparator<Student> another;
public ComplexComparator(Comparator<Student> one,
Comparator<Student> another) {
this.one=one;
this.another=another;
}
#Override
public int compare(Student one, Student another) {
//code given above
} }

Need Help In Sorting A Vector Of Objects

public class Sorting {
Vector<Talk> sorty(Vector <Talk> s) {
Collections.sort(s);
return s;
}
}
I need to sort Objects of the class Talk but I keep getting the error of
"Bound mismatch".
Talk Class is something like this:
public class Talk {
String name;
int duration;
public int compareTo(Talk t) {
int compare = t.duration;
return this.duration - compare;
}
}
Your Talk class needs to implement the Comparable interface if you want to sort lists containing it:
public class Talk implements Comparable<Talk> {
Note that it is not safe to compare int values by subtracting them from each other, unless you know that both values are only going to be positive (or not more than Integer.MAX_VALUE apart, to be precise). The reason is that an int will overflow and incorrectly turn negative if the values are more apart than that. Doesn't happen a lot, but it's a difficult bug to trace if it does happen, so better to get yourself used to an alternative.
A better way to compare, which always works, is to call Integer.compare(int, int):
public int compareTo(Talk t) {
return Integer.compare(duration, t.duration);
}
Talk does implement a compareTo method, but it doesn't implement the Comparable interface, which is where the compareTo should be overriden from.
Change your Talk to:
public class Talk implements Comparable{
String name;
int duration ;
#Override
public int compareTo(Object o)
{ Talk t = (Talk)o;
int compare = t.duration;
return this.duration - compare;
}
}
For me, I always prefer a fixed -1,0 or 1 return:
#Override
public int compareTo(Object o)
{ Talk t = (Talk)o;
int compare = t.duration;
return this.duration == compare ? 0 : this duration > compare ? 1 : -1;
}
but this is not mandatory.
I would, however, recommend to reconsider the access modifiers of your variables. Usually, private variables are recommended over package visibility.
I hope i can help you.
public class TestSorting {
/**
* #Desc:
*
* #param args
*
* #Author: luochao
* #CreateTime: 2016年2月3日
*/
public static void main(String[] args) {
Vector<Talk> vector = new Vector<Talk>();
vector.add(new Talk("centos",3));
vector.add(new Talk("linux",1));
vector.add(new Talk("java",2));
}
}
class Talk implements Comparable<Talk> {
private String name;
private int duration;
public Talk(String name,int duration) {
this.name = name;
this.duration = duration;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
#Override
public int compareTo(Talk o) {
int compare = o.duration;
return -(this.duration - compare);
}
}

Comparing two class objects with a method

I have a multitude of objects that are created with multiple instance variables (a string a multiple integers)
I have to create a method that will check for equality between the object that executes the method and another object. By that I mean that I would want to see whether all the instance variables are the same for two objects by calling a method. I'm thinking of something like the equals method (string1.equals(string2)), but can I do the same for an object with multiple instance variables which are not all strings?
example:
//object1
String name1= keyb.nextLine();
int age1= keyb.nextInt();
int monthborn1;
//object2
String name2=keyb.nextLine();
int age2 = keyb.nextInt();
int monthborn2;
I need to make a method that compare both objects and sees if they are equal or not.
Thank you very much.
Yes, you can create an equals method for your class. For example:
public final class Person {
private final String name;
private final int age;
private final int birthMonth;
public Person(String name, int age, int birthMonth) {
this.name = Objects.requireNonNull(name);
this.age = age;
this.birthMonth = birthMonth;
}
#Override
public boolean equals(Object o) {
if (o instanceof Person) {
Person rhs = (Person) o;
return name.equals(rhs.name)
&& age == rhs.age
&& birthMonth == rhs.birthMonth;
}
return false;
}
// Any time you override `equals`, you must make a matching `hashCode`.
// This implementation of `hashCode` is low-quality, but demonstrates
// the idea.
#Override
public int hashCode() {
return name.hashCode() ^ age ^ birthMonth;
}
}
In Java you usually have to manually check every field like this:
class MyObject {
String name;
int age, monthborn;
public boolean isEqual(MyObject other) {
return Objects.equals(name, other.name) &&
age == other.age && monthborn == other.monthborn;
}
}
Objects.equals is used here which is null-safe equivalent of name.equals(other.name). When you add new fields you will have to add new checks in your method as well. The alternative would be to utilize reflection, but it looks ugly and has significant performance drawback. Here's a draft example how to do this (do not take into account possible inheritance):
import java.lang.reflect.Field;
import java.util.Objects;
public class ObjectUtil {
public static <T> boolean allFieldsEqual(T o1, T o2) throws IllegalAccessException {
if(o1 == o2) return true;
if(o1.getClass() != o2.getClass()) return false;
for(Field field : o1.getClass().getDeclaredFields()) {
field.setAccessible(true);
if(!Objects.equals(field.get(o1), field.get(o2))) {
return false;
}
}
return true;
}
}
class MyObject {
String name;
int age, monthborn;
public boolean isEqual(MyObject other) {
try {
return ObjectUtil.allFieldsEqual(this, other);
} catch (IllegalAccessException e) {
return false;
}
}
}
This way upon adding the new field the isEqual method will take it into account as well. However I would not recommend such solution.
Please see this answer . Also, since you are overriding the equals method you should also override the hashcode method (also covered in the linked post)
Once you compare two objects you have to consider about all the members of the class.
We will assume that we have a class named B and with two member variables age and name.
class B :
public class B {
String name;
int age;
public B(String name, int age) {
this.age = age;
this.name = name;
}
}
Then lets compare the two different objects of same class using equals and hashcode methods which are inherited to our class B from Object class.
class A to compare :
public class A {
public static void main(String args[]){
B b1 = new B("a", 22);
B b2 = new B("a",22);
System.out.println(b1.equals(b2));
System.out.println(b1.hashCode());
System.out.println(b2.hashCode());
}
}
As soon as we compile and run class A we will get following out-puts.
false
705927765//returns int value
366712642//returns int value
But here in the class A we have passed same parameters to both objects of the B. Which means we are getting what we did not expect because of equals and hashcode methods which are in Object class not doing what we need.
So in this case we have to override these methods in our class B to make it success.
Class B after override done:
public class B {
String name;
int age;
public B(String name, int age) {
this.age = age;
this.name = name;
}
#Override
public boolean equals(Object obj) {
boolean flag = false;
if (obj instanceof B) {
B b = (B) obj;
if (this.age == b.age) {
if (this.name.charAt(0)==b.name.charAt(0))) {
flag = true;
} else {
flag = false;
}
} else {
flag = false;
}
} else {
flag = false;
}
return flag;
}
#Override
public int hashCode() {
return this.age+this.name.charAt(0);
}
}
If we run our class A again we could get follwing result :
true
119
119
Which means our work is done.

Java TreeSet sorting objects by value

I posted about this application yesterday, but now I'm having a different problem. I'm currently working on this application for tracking track (tracking track?) day runs and displaying a leaderboard. This is for a class so I'm not looking for code necessarily, just some thoughts on how to go about it. Anyway, the application currently will take input information (from the bottom textfields), create a TreeSet of RaceEntrant objects (class shown below), and create a queue on the right which is emptied as the participants go through their runs. The problem is, I need the TreeSet to be sorted in the (grey) leaderboard area from smallest to largest runTime and update while the times are entered at the top. I'm kind of unsure how to have it sort the objects specifically by the runTime. Any help is appreciated.
RaceEntrant Class
class RaceEntrant
{
private String name,
car;
private double runTime;
public RaceEntrant(String name, String car)
{
this.name = name;
this.car = car;
}
public String getName()
{
return name;
}
public String getCar()
{
return car;
}
public double getTime()
{
return runTime;
}
public void setTime(double time)
{
this.runTime = time;
}
#Override
public String toString()
{
StringBuilder sb = new StringBuilder("");
sb.append(getName());
sb.append(" ");
sb.append(getCar());
sb.append("\n" );
sb.append("Best time: " + getTime() + "\n");
return sb.toString();
}
}
This is an example of the current operation - the RaceEntrant(s) are displayed in order of their runs, not sorted by anything. I apologize for the lengthy post.
Your class, RaceEntrant, should implements Comparable, and you can control order in the implemented method compareTo.
Your class could look like this:
class RaceEntrant implements Comparable<RaceEntrant>
{
private final String name,
car;
private double runTime;
public RaceEntrant(final String name, final String car)
{
this.name = name;
this.car = car;
}
public String getName()
{
return name;
}
public String getCar()
{
return car;
}
public double getTime()
{
return runTime;
}
public void setTime(final double time)
{
this.runTime = time;
}
#Override
public String toString()
{
final StringBuilder sb = new StringBuilder("");
sb.append(getName());
sb.append(" ");
sb.append(getCar());
sb.append("\n" );
sb.append("Best time: " + getTime() + "\n");
return sb.toString();
}
#Override
public boolean equals(final Object obj) {
if(this == obj) return true;
if (obj instanceof RaceEntrant){
return (((RaceEntrant) obj).getTime() == runTime) && ((RaceEntrant) obj).getName().equals(name) && ((RaceEntrant) obj).getCar().equals(car);
}
return false;
}
#Override
public int hashCode() {
return new Double(runTime).intValue();
}
#Override
public int compareTo(final RaceEntrant o) {
return new Double(o.runTime).compareTo(this.runTime)*-1;
}
}
In your RaceEntrant class:
class RaceEntrant implements Comparable<RaceEntrant>{
//..
public int compareTo(RaceEntrant re){
return getTime().compareTo(re.getTime());
}
#Override //optional for Sets
public boolean equals(Object o){
If(o != null && o instanceOf RaceEntrant){
RaceEntrant entrant = (RaceEntrant)o;
return getName().equals(entrant.getName() &&
getCar().equals(entrant.getCar()) &&
getTime() == entrant.getTime();
}
}
}
Then you can sort your List (probably ArrayList) by runTime.
You could also use a TreeSet (this should be sorted automatically) and define a equals method on runTime + name + car if that's a possible approach.
I guess the TreeSet is not the right data structure. A TreeSet is above all a Set -- which keys are considered unique based on comparison.
I think you can have identical run times?
Maybe just use an ArrayList and sort it using Collections.sort() with a custom Comparator.

Overriding hashcode and equals method in java?

I have the classes below:
public class Sample implements java.io.Serializable{
//POJO with two fields and getters/setters
private String name;
private Integer id;
//This POJO does not override equals() and hashCode()
}
public class B{
private Sample sample;
//here i need override hashcode and equals() based on **sample** property.
}
When i tried overriding equals() and hashCode() in the B class I got the error below in Eclipse.
The field type com.mypackage.Sample does not implement hashCode() and equals() - The resulting code may not work correctly.
Now how can I compare two B instances whether equals or not based on the Sample property?
I cannot modify Sample class.
are you looking something like following? Just try it, as from your question i think you want to compare contents of your Sample class also.
class Sample implements java.io.Serializable{
//POJO with two fields and getters/setters
private String name;
private Integer id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
//This POJO does not override equals() and hashCode()
}
public class Beta implements Comparable{
private Sample sample;
public Sample getSample() {
return sample;
}
public void setSample(Sample sample) {
this.sample = sample;
}
#Override
public int compareTo(Object o) {
if(!(o instanceof Beta)){
return -1;
}
}if(((Beta)o).getSample().getName().equals(this.sample.getName())){
return 0; // return true if names are equal
}
if(((Beta)o).getSample().getId().equals(this.sample.getId())){
//if name are notequal and IDs are equal, do what you need to do
}
return -1;
}
public static void main(String[] args) {
Beta b = new Beta();
Sample s = new Sample();
s.setId(10);
s.setName("Name1");
b.setSample(s);
Beta b2 = new Beta();
Sample s2 = new Sample();
s2.setId(20);
s2.setName("Name2");
b2.setSample(s2);
System.out.println(b2.compareTo(b));
Beta b3 = new Beta();
Sample s3 = new Sample();
s3.setId(10);
s3.setName("Name1");
b3.setSample(s3);
System.out.println(b3.compareTo(b));
}
}
Overriding approach
class Sample implements java.io.Serializable{
//POJO with two fields and getters/setters
private String name;
private Integer id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
//This POJO does not override equals() and hashCode()
}
public class Beta /*implements Comparable*/{
private Sample sample;
public Sample getSample() {
return sample;
}
public void setSample(Sample sample) {
this.sample = sample;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Beta other = (Beta) obj;
if ((this.getSample() == null) && (other.getSample() == null)){
return true;
}
if ((this.getSample().getId().equals(other.getSample().getId())) && (this.getSample().getName().equals(other.getSample().getName()))) {
return true;
}
return false;
}
#Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (this.getSample().getName() != null ? this.getSample().getName().hashCode() : 0);
hash = 53 * hash + (this.getSample().getId() != null ? this.getSample().getId().hashCode() : 0);
return hash;
}
/* #Override
public int compareTo(Object o) {
if(!(o instanceof Beta)){
return -1;
}
if(((Beta)o).getSample().getId().equals(this.sample.getId()) && ((Beta)o).getSample().getName().equals(this.sample.getName())){
return 0;
}
return -1;
}*/
public static void main(String[] args) {
Beta b = new Beta();
Sample s = new Sample();
s.setId(10);
s.setName("Name1");
b.setSample(s);
Beta b2 = new Beta();
Sample s2 = new Sample();
s2.setId(20);
s2.setName("Name2");
b2.setSample(s2);
System.out.println(b2.equals(b));
Beta b3 = new Beta();
Sample s3 = new Sample();
s3.setId(10);
s3.setName("Name1");
b3.setSample(s3);
System.out.println(b3.equals(b));
}
If you don't explicitly override .equals(), they will be compared based solely off of their references (despite not having a equals(), every object inherits one from Object). If you only want B to be compared based off of Sample, then simply do the following:
#Override
public boolean equals(Object o)
{
if (o istanceof B)
{
return sample.equals(o.sample)
}
return false;
}
Additionally, you should then override hashCode() (and compareTo()) to maintain the contract between equals() and hashCode(). Hence, you should also have the following:
#Override
public int hashCode()
{
return sample.hashCode();
}
EDIT (in response to comment):
My requirement is first i need to check equals property against "name"
property of Sample. IF names are equals then both objects are equal.
If names are not equals then i need to check for equality against "ID"
property of Sample. How can i do that? Thanks!
Determining whether Samples are equivalent should be handled in Sample, by overriding equals(). If equals() for Sample bases off of name and id, then you're fine. If you want to compare Samples in B differently than they are normally compared, then you're not going to be able to maintain the contract between equals() and hashCode() for B if you use hashCode() or equals() from Sample, which means that your hashCode() and equals() for B should be cannot call equals() or hashCode() from Sample. See this tutorial for how to override based on specific fields.

Categories