How to compare object parameter to another object parameter (inside array) - java

What do I need to write inside the " if " statement in order to check if the object's variable (number) is equal to any of the object's variables (number) inside my array?
public class Question{
private int number;
private String questionString;
private int index = 0;
public Question(int number, String questionString){
if(number < 0){
System.out.print("Number cannot be negative!");
}
if(questionString.equals(null) || questionString.trim().isEmpty()){
System.out.print("Question cannot be empty!");
}
this.number = number;
this.questionString = questionString;
}
public boolean equals(Object o){
if(o instanceof Question){
for(int i = 0; i < index; i++){
if(.... ){
}
}
return true;
}
return false;
}
}
Test Class (main Class), ofc not yet completed I just hope it gives you enough information, on how to proceed on my Question class:
public class Test{
String name;
Question[] questions;
public Testi(String name, int nrQuestions){
}
public static void main(String[]args){
}
}

This should do:
public boolean equals(Object o){
if (o == null )
return false;
if(o instanceof Question){
if (((Question)o).number == this.number ){
if (this.questionString.equals(((Question)o).questionString)){
return true;
}
}
}
return false;
}
Be careful though, if you're implementing equals() you should also implement hashCode(). It's your "model" that should make clear when two objects are equal. In your case, I would say that when two Question's number are the same, then the Question is also the same. If not, you should also add questionString to the check

From your last comment, I think I now understand your REAL issue: You tried to use the equals() method to compare an object to an array of objects that you pass to this method, right? The call to equals would look like this:
Question[] questions;
question.equals(questions);
Technically this is possible with Java, but strongly discouraged I would say. equals() should only be used to compare to one object at a time (and stick to the hashCode/equals contract).
So I suggest you to do something like this:
//your application code
public boolean equals(Object obj){
if (obj instanceof Question){
return (((Question)obj).number == this.number);
}
return false;
}
//use this to obey the equals/hashCode contract
public int hashCode() {
return this.number;
}
// your test code -------------
public void testQuestions(Question testAgainstThisObject, Question[] testQuestions) {
for (Question testThisQuestion : testQuestions) {
assertTrue(testAgainstThisObject.equals(testThisQuestion));
}
}
Another way would be to use a specialised method in Question.java, something like this:
public boolean isThisContained(Question[] questions) {
for (Question question : questions) {
if (this.equals(question)) {
return true;
}
}
return false;
}

Related

Java arraylist of objects how to search for elements error

I am trying to Implement a class named Parade using an ArrayList, which will manage instances of class Clown. Each Clown needs to be identified by all object data String for their name, int id and double size. I join a new Clown to the end of the Parade. Only the Clown at the head of the Parade (i.e., the first one) can leave the Parade. In addition, I write a method called isFront that takes a Clown as parameter and returns true if the passed clown is at the front of the parade otherwise returns false. Create a test application to demonstrate building a parade of three or four clowns and include your own name. Then, remove one or two, and add another one or two. Also, test the isFront method by passing different clowns to the method.
I have a code but it is not returning true for the isFront method, I am trying to use contains method I also tried to use Comparable interface Clown but it did not work that well. Not sure what to do.
import java.util.ArrayList;
public class Main
{
public static void main(String[] args)
{
Parade circus = new Parade();
circus.addClown(new Clown("Bobby",9,12.0));
circus.addClown(new Clown("Clair", 2, 11.0));
circus.addClown(new Clown("Tony",6,10.0));
circus.addClown(new Clown("Sarah",3,5.0));
circus.display();
System.out.println(circus.isFront(new Clown("Bobby", 9, 12.0)));
}
}
import java.util.ArrayList;
public class Parade
{
private static ArrayList<Clown> parade;
private int top;
public Parade()
{
top=0;
parade= new ArrayList<Clown>();
System.out.println(parade);
}
public void addClown(Clown c)
{
parade.add(c);
top++;
}
public void removeClown() //(Clown c)
{
parade.remove(0);
top--;
}
public void display()
{
System.out.println(parade);
}
public void getData()
{
parade.get(0);
}
public void setData()
{
parade.set(1,new Clown("Claire",2,5.0));
System.out.println(parade);
}
public int getTop()
{
return top;
}
public boolean isFront(Clown c)
{
return !parade.isEmpty() && c.equals(parade.get(0));
}
//exceptions
}
public class Clown
{
private String name;
private int id;
private double size;
public Clown(String name, int id, double size)
{
this.name=name;
this.id=id;
this.size=size;
}
public String getName()
{
return name;
}
public int getId()
{
return id;
}
public double getSize()
{
return size;
}
public String toString()
{
return name.toString() + id + size;
}
public boolean equals(Object o) {
if (o instanceof Clown c) {
return this.getName().equals(c.getName()) && this.getId() == c.getId() && this.getSize() == c.getSize();
}
return false;
}
}
their is not much info in our textbook about this stuff Java FOundations 5th e Lewis like working with objects and arraylists it skips it and assumes you already know it lol..
Firstly, objects in Java are, by default, compared by reference. So, even if you create two Clown objects with the exact same properties, Java sees them as different objects because both those object references are not the same, they are both referring to different memory locations. You can override this behavior and ask Java to compare it as you want by overriding the equals() method of the Object class:
public class Clown {
private String name;
private int id;
private double size;
public Clown(String name, int id, double size) {
this.name=name;
this.id=id;
this.size=size;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public double getSize() {
return size;
}
#Override
public boolean equals(Object o) {
if (o instanceof Clown) {
Clown c = (Clown) o;
return this.getName().equals(c.getName());
}
return false;
}
#Override
public int hashCode() {
return this.getId();
}
#Override
public String toString() {
return name.toString() + id + size;
}
}
This will help with contains()(it internally uses equals()).
Secondly, you can just compare your clown with the first clown to see if it is the one at the front:
public boolean isFront(Clown c) {
return !parade.isEmpty() && c.equals(parade.get(0));
}
The isFront() method will return true if the parade is not empty and the clown c is equal to to the first clown in the parade. get(0) retrieves the first clown in the parade.
As per your comment, if you want that two clowns be equal only if all their properties are equal, change your equals method to:
#Override
public boolean equals(Object o) {
if (o instanceof Clown) {
Clown c = (Clown) o;
return this.getName().equals(c.getName()) &&
this.getId() == c.getId() &&
this.getSize() == c.getSize();
}
return false;
}
The equals() method is of the Object class which is the parent class of all Java classes. It defines how to compare two objects.
Its signature is as follows:
public boolean equals(Object obj)
As we're overriding, its signature must be the same in the derived class, in our case in class Clown. Its parameter is of type Object not Clown. Any type can be converted to Object, if I compare an object of Clown to another type, like:
Clown c = new Clown("X", 1, 10);
if ( c.equals(objectOfAnotherType) ) {..}
it will still work.
So we use the instanceof operator to check if that another object is also a Clown. If it is not an instance of Clown, we return false but if it is, we convert/cast that object to Clown, only then we can call getName() and other getter methods:
if (o instanceof Clown) {
Clown c = (Clown) o; //Casting happens here
return this.getName().equals(c.getName()) &&
this.getId() == c.getId() &&
this.getSize() == c.getSize();
}
return false;
Java 14 introduced a shortcut for this, instead of these steps:
if (o instanceof Clown) {
Clown c = (Clown) o;
we can simply write:
if (o instance of Clown c)
which does the casting for us and stores it in c.
Lastly, I have also overriden Object.hashCode() because you have to when you override equals(), here's why.

How to test if a list of objects contains an object that contains a particular string as an attribute?

I'm trying to figure out how to test if a list of objects contains an object that contains a particular string as an attribute.
So here Is my list of objects
ArrayList<mObject> objectsList;
And here is my mObject class
public class mObject {
String x = "True";
}
And here I try to make some kind of test
if(ObjectsList.contains(object.x == "True")){
return true;
} else {
return false;
}
I know the syntax is kind of ridiculous, but how can I make it technically correct?
For previuos versions of Java 8:
public class MObject {
private String x = "True";
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
You can iterate over the list:
ArrayList<MObject> objectsList; //Init your object list.
for(MObject object : objectsList) {
if(object.getX().equals("True")) {
return true;
} else {
return false;
}
}
Java 8:
List<mObject> list = ObjectsList.stream().filter(obj -> obj.x.equals( "True")).collect(Collectors.toList()).;
if (list.size() != 1) {
return false;
} else {
return true;
}
and, please, observe java naming conventions
for Java 8 you can use
objectsList.stream().anyMatch(myObject -> myObject.x.equals("True"));
please look at the code standards about naming variables (lowercase start and camel case) and classes (uppercase start)
PS: As your variable is a string with "True" value - are you sure not wanting to have a boolean?
I override equals() method to be able to use .contians() because it comparing objects using equals(),as your List is List<mObject> (List of custom object) so i had to override the .equals() to be able to use .contains() probably
public class mObject {
private String x = "True";
public String getX(){
return x;
}
public void setX(String x){
this.x=x;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final mObject other = (ttt) obj;
if (!Objects.equals(this.x, other.x)) {
return false;
}
return true;
}
}
To make your test :-
if(ObjectsList.contains(object) && object.getX().equals("True")){
return true;
} else {
return false;
}
Please see the difference between == and .equals() when comparing string
from this and that link

Search ArrayList filled with Objects for specific ID

I'm facing the following problem, it´s for a quiz (shuffled answers, not the same amount of answers for every question):
I have two Lists listOfAnswers and listOfUserAnswers (both are type List<Answer>).
Answer is defined as followed:
public class Answer {
int answerId;
int answerIsCorrect;
String answer;
public Answer() {
}
public void setId(int id) {
this.answerId = id;
}
public Answer setAnswer(String answer) {
this.answer = answer;
return this;
}
public void setAnswerIsCorrect(int answerIsCorrect) {
this.answerIsCorrect = answerIsCorrect;
}
public int getId() {
return this.answerId;
}
public String getAnswer() {
return this.answer;
}
public int getAnswerIsCorrect() {
return this.answerIsCorrect;
}
public String toString() {
return String.format("Answer[%s, %s, %s]", this.answerId, this.answerIsCorrect, this.answer);
}
}
The listOfAnswers object holds EVERY answer for each question (specified in listOfQuestions of type List<Question>, but this is not the problem).
The listOfUserAnswers object holds every answer, the user has SELECTED (selected by a checkbox). At this point, the app does not know if the answer selected by the user is right or wrong.
Now, when calculating the result, I want iterate through listOfAnswers and I check, if the answerId (listOfAnswers.get(i).getId()) is also available in listOfUserAnswers.
But how does this work? I can't check with listOfUserAnswers.contains(...), I think. Or am I wrong?
Please, comment if you have trouble understanding....
You can't check if listOfUserAnswers.contains() because you haven't defined an Answer.equals() method. You would have to iterate through both lists like so:
for(Answer answer : listOfAnswers) {
for(Answer userAnswer : listOfUserAnswers) {
if(answer.getId() == userAnswer.getId()) {
//answer matches
}
}
}
Alternatively, you could define an Answer.equals() method:
#Override
public boolean equals(Object obj) {
return obj instanceof Answer && ((Answer)obj).answerId == this.answerId;
}
Now instead of a nested loop, you can do:
for(Answer answer : listOfAnswers) {
if(listOfUserAnswers.contains(answer) {
//answer matches
}
}
EDIT: As mentioned in the comments, you should always override hashCode() when overriding equals(). In this case, the simplest implementation would be:
#Override
public int hashCode() {
return answerId;
}
To use the ArrayList.contains() method you'll need to override the Object.equals() method. So in this case you'd add to your Answer class something like:
public boolean equals(Object o){
if(o instanceof answer){
return this.answerId == ((Answer) o).answerId;
} else return false;
}
And then you can use it.
Checking for listOfUserAnswers.contains() is not possible unless you override the following method:
#override
public boolean equals(Object o){
if(this.answerId == ((Answer)o).answerId ) return true;
return false;
}
You can, just overwrite equals method as follows:
public boolean equals(Object o) {
if(!(o instanceof Answer) ) return false;
return answerId == ((Answer)o).answerId;
}
and call contains.

Inheritance - using super.equals() in subclasses that override methods used in equals of superclass

I've been testing a code and stumbled across a problem: Should you call super.equals() method in subclass that can override some of the methods used in equals() method of the super class?
Let's consider the following code:
public abstract class Item {
private int id;
private float price;
public Item(int id, String name, float price, String category) {
this.id = id;
this.name = name;
this.price = price;
this.category = category;
}
public int getID() {
return id;
}
public float getPrice() {
return price;
}
#Override
public boolean equals(Object object){
if(object instanceof Item){
Item item = (Item) object;
if( id == item.getID()
&& price == item.getPrice())
{ return true; }
}
return false;
}
}
And the subclass DiscountedItem:
public class DiscountedItem extends Item {
// discount stored in %
private int discount;
#Override
public boolean equals(Object object) {
if(object instanceof DiscountedItem){
DiscountedItem item = (DiscountedItem) object;
return (super.equals(item)
&& discount == item.getDiscount()
);
}
return false;
}
public int getDiscount() {
return discount;
}
#Override
public float getPrice() {
return super.getPrice()*(100 - discount);
}
}
I've been just re-reading Angelika Langer's secrets of equals(), where she even states:
There is agreement that super.equals() should be invoked if the class has a superclass other than Object.
But I think it's highly unpredictable when the subclass will override some of the methods. For instance when I compare 2 DiscountedItem objects using equals, the super method is called and item.getPrice() is dynamically dispatched to the correct method in the subclass DiscountedItem, whereas the other price value is accessed directly using variable.
So, is it really up to me (as I should implement the method correctly) or is there a way around it?
Compare instance variables directly rather than comparing an instance variable to its related getter method.
For example, change
&& price == item.getPrice())
to
&& this.price == item.price)
The getter method is unnecessary since private instance variables are only inaccessible outside the class structure.
Note:
I previously recommended the following:
&& this.getPrice() == item.getPrice())
While it will work in the question's example, it is not well suited for all cases. Consider if the subclass DiscountedItem declared the method getPrice as such:
#Override
public float getPrice() {
return Math.floor(super.getPrice());
}
This would result in the false equivalence:
DiscountedItem firstItem = DiscountedItem(1, "", 1.1, "");
DiscountedItem secondItem = DiscountedItem(1, "", 1.0, "");
firstItem.equals(secondItem); // Returns true despite different prices.
The implementation of equals should depend on state and type, but not functionality. You went wrong in your base class:
#Override
public boolean equals(Object object){
if(object instanceof Item){ // Type check- good!
Item item = (Item) object;
if( id == item.getID() // Depends on functionality- bad!
&& price == item.getPrice()) // Depends on functionality- bad!
{ return true; }
}
return false;
}
item.getID() and item.getPrice(), as you've noticed, can be overwritten to break the contract of Item.equals().
#Override
public boolean equals(Object object){
if(object instanceof Item){ // Type check- good!
Item item = (Item) object;
if( id == item.id // Depends on state- good!
&& price == item.price) // Depends on state- good!
{ return true; }
}
return false;
}
This will never be broken by a child class. Further, it enables the child to meaningfully delegate to it.
#Override
public boolean equals(Object object) {
if(object instanceof DiscountedItem){
DiscountedItem item = (DiscountedItem) object;
return (super.equals(item)
&& this.discount == item.discount
);
}
return false;
}
The child only needs to worry about comparing the data that it owns.
Oh my, I guess I just had to post the question to get it..
To get rid of the problem, instead of directly accessing variables - call the getters!
#Override
public boolean equals(Object object){
if(object instanceof Item){
Item item = (Item) object;
if( this.getID() == item.getID()
&& this.getPrice() == item.getPrice())
{ return true; }
}
return false;
}
This code no longer has the problem when overriding methods.
If you call the equals of the DiscountedItem when can you have a problem?
If something is DiscountedItem and something else is Item these two
are never equal as per equals. Right? So I don't see a problem if you
always call the getters.
Also, you need to override hashCode if you override equals.

How to define multiple equals() function for a class

I want to override "public boolean equals(Object obj)" function, for name and age, in my class named MyObject whose structure is given below
public class MyObject{
private String name;
private int age;
}
How can i ?
#balusC :
What about this ?
vo = new MyObject() {
public boolean equals(Object obj) {
return ((MyObject)obj).name().equals(this.getName());
}
vo = new MyObject() {
public boolean equals(Object obj) {
return ((MyObject)obj).age() == (this.getAge());
Your question is a bit vague, but if the sole purpose is to have different sorting algorithms depending on what property you'd like to use, then rather use a Comparator.
public class Person {
private String name;
private int age;
public static Comparator COMPARE_BY_NAME = new Comparator<Person>() {
public int compare(Person one, Person other) {
return one.name.compareTo(other.name);
}
}
public static Comparator COMPARE_BY_AGE = new Comparator<Person>() {
public int compare(Person one, Person other) {
return one.age > other.age ? 1
: one.age < other.age ? -1
: 0; // Maybe compare by name here? I.e. if same age, then order by name instead.
}
}
// Add/generate getters/setters/equals()/hashCode()/toString()
}
which you can use as follows:
List<Person> persons = createItSomehow();
Collections.sort(persons, Person.COMPARE_BY_NAME);
System.out.println(persons); // Ordered by name.
Collections.sort(persons, Person.COMPARE_BY_AGE);
System.out.println(persons); // Ordered by age.
As to the actual equals() implementation, I'd rather let it return true when the both Person objects are techically or naturally identical. You can use either a DB-generated PK for this to compare on technical identity:
public class Person {
private Long id;
public boolean equals(Object object) {
return (object instanceof Person) && (id != null)
? id.equals(((Person) object).id)
: (object == this);
}
}
or just compare every property to compare on natural identity:
public class Person {
private String name;
private int age;
public boolean equals(Object object) {
// Basic checks.
if (object == this) return true;
if (object == null || getClass() != object.getClass()) return false;
// Property checks.
Person other = (Person) object;
if (name == null ? other.name != null : !name.equals(other.name)) return false;
if (age != other.age) return false;
// All passed.
return true;
}
}
Don't forget to override hashCode() as well when you override equals().
See also:
Object ordering
Sorting an ArrayList of objects
Overriding equals() and hashCode()
I'm not exactly sure what you're aiming at with this. The general expectation of equals() is that it returns false for null and objects of other classes and performs value equality on the relevant fields of the class in question.
While you can certainly handle String and Integer in the following way:
public boolean equals(Object o) {
if (o == null) return false;
if (o instanceof String) return name.equals(o);
if (o instanceof Integer) return ((Integer)o) == age;
...
}
this breaks the contract for equals so you can't do it (except not without things going wrong in very weird ways).
equals is an equivalence relation, so it has to be reflexive, symmetric and transitive. The symmetric part here is key, since if a.equals(b) then b.equals(a). Both String and Integer won't do that for you.
If you want just helper functions that check whether the name or the age is equals to a given name/age, then you can do that without using equals():
public boolean equalsName(String name) { return name.equals(this.name); }
public boolean equalsAge(int age) { return age == this.age; }
Just keep it short and simple (aka KISS principle): write setters and getters. Something like in the following example:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
And then in the method you need to do the check you can write:
Person person = new Person();
if(person.getName().equals("Something")) doThis();
if(person.getAge() == 1337) doThat();
Not sure what you mean by "multiple equals()". If you want compare both your fields, you just need to override the equals method like this,
public boolean equals( Object o )
{
if ( o != null && o instanceof MyObject )
{
MyObject m = (MyObject) o;
if (this.name == null)
return false;
return this.name.eqauls(m.name) && this.age == m.age;
}
return false;
}
/// Compute a hash code for the pair.
public int hashCode()
{
int code = name == null ? 0 : name.hashCode();
return code ^ age;
}
It's a good practice to change hashCode whenever you change equals so HashMap works efficiently with your object.
if you do want to override equals, it should look something like this:
static private <T> boolean checkEquals(T t1, T t2)
{
return (t1 == null) ? (t2 == null) : t1.equals(t2);
}
#Override public boolean equals (Object o)
{
if (o instanceof MyObject)
{
MyObject obj = (MyObject)o;
return checkEquals(this.name, obj.getName())
&& this.age == o.getAge();
}
else
return false;
}
#Override public int hashCode()
{
// implement hashCode
}
You need to override both hashCode() and equals() or neither. And you also should make sure your class is final, otherwise there are potential pitfalls with equals.
public class MyObject {
private String name;
private int age;
#Override
public boolean equals(Object o){
if(o instanceof MyObject){
MyObject otherObject = (MyObject)o;
if(name == null){
return otherObject.name == null && otherObject.age == age;
} else {
return name.equals(otherObject.name) && otherObject.age == age;
}
} else {
return false;
}
}
// When we overriding equals it is a good practice to override hashCode
// for consistecy
#Override
public int hashCode(){
int nameCode = (name == null) ? 0 : name.hashCode();
// See Item 9 in book Effective Java 2nd Edition
return 31 * nameCode + age;
}
}

Categories

Resources