Using the boolean object equals() in my implemented equals() - java

So I am doing a junit test in Java.
I am supposed to test two concrete types
public class BoolValue implements Value{
private boolean item;
//the Constructor
public BoolValue(boolean data){
item = data;
}
//checks to see if the current object is of the same type as the parameter
public boolean equals(Value v){
boolean result = false;
if (v instanceof BoolValue) {
if(this == v)
result = true;
}
return result; //true if equal
}
// returns current state string
public String toString(){
return " "+item;
}
}
This is the test case in my test file
#Test
public void testBoolean(){
BoolValue value = new BoolValue(true);
BoolValue value2 = new BoolValue(true);
assertEquals(true, value.equals(value2));
}
It returns false instead of the expected true
In the equals method, I want to compare two boolean types but I can't use the java.object equals() because the program reads it as the class equals() so its recursive.
How do I call the java.object equals() for comparing boolean types. Also, am I going about this the right way

if (v instanceof BoolValue) {
if(this == v)
result = true;
}
You cannot use == when you want new BoolValue(true).equals(new BoolValue(true)). You need to compare the two item inside them.
Also, you need to accept Object to get a "proper" equals method.
#Override
public boolean equals(Object v){
return (v instanceof BoolValue && ((BoolValue)v).item == this.item);
}
And when you override equals, you also need to override hashCode.
#Override
public int hashCode(){ return item ? 0 : 1; }
Finally (unless you intend to make these "values" mutable), since there are only two possible values, you should make the constructor private and provide the two values as static fields instead (you could also use an enum).
public class BoolValue implements Value {
private final boolean item;
private BoolValue(boolean v){
this.item = v;
}
public static final BoolValue TRUE = new BoolValue(true);
public static final BoolValue FALSE = new BoolValue(false);
public static BoolValue valueOf(boolean x){
return x ? TRUE : 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 fix HashSet that allows duplicates?

I'm using a java.util.Set interface with a java.util.HashSet implementation and storing it in a Map.
I add an object to a Set then retrieve the Set object again and am able to add another object that is equal to the first.
When adding the seemingly equal objects, Set.add returns true and two equal objects are stored in a HashSet. How is this possible and what can I do to fix this apparent breakage of the Set contract?
I'm using Java 12 via IntelliJ IDEA 2018.3.6 and have checked my java.lang.Object.hashCode implementation for the class of the two objects I add to the Set, with both returning the same hash code. I've also checked the java.lang.Objects.equals implementation and it returns true when the method is used to check their equality. Both objects are wrapped in another object, Entity, but that only forwards the objects' hashCode and equals implementations.
class Model {
...
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Offer)) {
return false;
}
Offer offer = (Offer) obj;
return Objects.equals(id, offer.id)
&& Objects.equals(name, offer.name)
;
}
#Override
public int hashCode() {
int result = 1;
result = 31 * result + Objects.hashCode(id);
result = 31 * result + Objects.hashCode(name);
return result;
}
...
}
class Store {
...
private static class Entry {
Object value;
Entry(Object value) {
this.value = value;
}
Object getValue() {
return value;
}
#Override
public boolean equals(Object obj) {
return Objects.equals(value, obj);
}
#Override
public int hashCode() {
return value.hashCode();
}
#Override
public String toString() {
return "Entry[value = " + value + "]";
}
}
...
private Map<Class<?>, Set<Entry>> data;
...
private Set<Entry> get(Class<?> type) {
return data.getOrDefault(type, new HashSet<>());
}
#Override
public void persist(Object obj) {
Entry entry = new Entry(obj);
Set<Entry> objects = get(obj.getClass());
if (objects == null) {
objects = new HashSet<>();
}
if (!objects.add(entry)) {
throw new ObjectExistsException
("Object already exists: " + obj);
}
data.put(obj.getClass(), objects);
}
...
}
When obj1 and obj2 of type Model are equal and objects already contains obj1 wrapped in an Entry object, I expect obj2 not to be added to objects when obj2 is wrapped in entry and for objects.add(entry) to return false then an ObjectExistsException to be thrown.
However, what actually is happening is objects.add(entry) returns true and obj2 wrapped in entity is being added to objects.
#Override
public boolean equals(Object obj) {
return Objects.equals(value, obj);
}
This isn't a correct implementation of Entry.equals. This potentially compares an Entry with the value held by the current entry. (Like comparing a letter with an envelope).
Make your equals method check that obj is an Entry, and get its value, and check equality to that.
You were right #Andy Turner, but it was #Andreas that pointed me in the right direction. I thought I would be lazy and not write a full equals method implementation, but it cost me. It should have been like this:
private static class Entry {
...
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Entry)) {
return false;
}
Entry entry = (Entry) obj;
return Objects.equals(getValue(), entry.getValue());
}
...
}
Thank you both.

Reflexive property in java Equals method

I am reading up on how to properly override the equals in Java, and ran into this sample. My first thought is that it would pass the reflexive property, but apparently it doesn't.
It basically returns false because of this line: if(this != tc) return true;
But isn't checking the same instance tc1, so tc1.equals(tc1), wouldn't it be passing a copy of the reference tc1, meaning they both are pointing to same TestClass object, and thus this and tc1 are essentially pointing to same object?
class TestClass {
int someVar;
TestClass(int i) {
someVar=i;
}
public boolean equals(Object tc) {
if (tc instanceof TestClass && this.someVar == ((TestClass) tc).someVar) {
if (this != tc) {
return true;
} else {
return false;
}
}
return false;
}
public int hashCode() {
return 1;
}
}
public class HashDemo {
public static void main(String []args) {
TestClass tc1 = new TestClass(20);
System.out.println(tc1.equals(tc1));
}
}
I think you have some of your if statements turned around.
Conventional equals method here would look something like this.
public boolean equals(Object that){
if (this == that) {
return true;
}
if (that instanceof TestClass && this.someVar == ((TestClass) that).someVar ) {
return true;
}
return false;
}
This is clearly not the right way to override the equals method, but it allows you to point the difference between "==" and "equals" on Objects
The egality between two references is done with the " == " operator.
The equals method is used to test the egality by values, that's why you can override it depending on your functionnal needs.
Regarding your code :
tc1 == tc1 -> TRUE
tc1.equals(tc1) -> FALSE

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

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;
}

Check if a Particular Object is in a List Using a Given Implementation of equals()

I need to check if an equivalent instance of a particular Object is in a List.
The Objects are instances of a Final Class that has an equals method that is too strict. I want to be able to provide a different implementation of equals to a "contains" method to check if the object is contained in the List.
The equals method in the class below will return false if the elements of partsInBox are in a different order; I need to change this behavior to be order indiscriminate.
public final class Box {
String category;
List<Integer> partsInBox;
#Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
Box box = (Box) o;
return category.equals(box.category)
&& partsInBox.equals(box.partsInBox);
}
}
I would like to be able to do something like this:
List<Box> boxes; // list that I am checking
Box myBox; // what I am checking for
boolean contained = contatins(boxes, box, new EqualsMethod() {
#Override
public boolean areEqual(Box b1, Box b2) {
if (b1 == b2) { return true; }
return b1.category.equals(b2.category)
&& b1.partsInBox.containsAll(b2.partsInBox);
}
});
What are my options for achieving this type of functionality?
The ideal solution would be changing the current behavior of the equals() method. However, it could be not possible for you if you don't have access to the other code.
Instead, you can use CollectionUtils.exists(collection, predicate) from Apache CollectionUtils.
http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/CollectionUtils.html
You can create a Predicate with the custom conditions you need to determine if your objects are equal enough.
Hope it helps.
Well since the class is final you can't extend it.
There is however the Comparator<T> interface which you could make use of, something like this:
public class BoxComparator implements Comparator<Box> {
#Override
public int compare(Box b1, Box b2) {
if (b1 == b2) { return 0; }
// return -1 or 0 or +1...
}
public static void main(String[] args) {
Box box1, box2;
...
boolean contains = new BoxComparator().compare(box1, box2) == 0;
}
}
I'm not completely sure from your code examples above if you want to compare a Box to another Box or a List<Box> - in the latter case you can't derive Comparator, but you could do something similar, for example a BoxInListComparator.
Hope this helps.
Equator.java
public interface Equator<T> {
boolean equals(T obj1, T obj2);
}
Some other class
public static <T> boolean contains(Collection<T> toSearch, T toSeek, Equator<T> equator) {
for (T oneItem : toSearch) {
if (equator.equals(oneItem, toSeek)) {
return true;
}
}
return false;
}
To use it
import static some.other.class.contains; // The contains method from the class above
List<Box> boxes; // list that I am checking
Box myBox; // what I am checking for
boolean contained = contains(boxes, box, new Equator<Box>() {
#Override
public boolean equals(Box b1, Box b2) {
if (b1 == b2) { return true; }
return b1.category.equals(b2.category)
&& b1.partsInBox.containsAll(b2.partsInBox);
}
});
You could use a Comparator with Java's built-in methods for sorting and binary search. Suppose you have a class like this, where a and b are the fields you want to use for sorting:
class Thing { String a, b, c, d; }
You would define your Comparator:
Comparator<Thing> comparator = new Comparator<Thing>() {
public int compare(Thing o1, Thing o2) {
if (o1.a.equals(o2.a)) {
return o1.b.compareTo(o2.b);
}
return o1.a.compareTo(o2.a);
}
};
Then sort your list:
Collections.sort(list, comparator);
And finally do the binary search:
int i = Collections.binarySearch(list, thingToFind, comparator);
It would be easier (but not so self-evidently inefficient) in Groovy, using Closures. Well, here we go in Java:
package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
// ------- Original code with comments added
public final class Box {
// these should be final and List<Integer> should be immutable using
// Collections.unmodifiableList() to avoid nasty surpises, and should
// possibly be pre-sorted
String category;
List<Integer> partsInBox;
#Override
public boolean equals(Object o) {
// same instance, then true (works if null passed, too)
if (this == o) {
return true;
}
// Null and not exactly same class (instanceof not needed as "final"), then false
if (o == null || getClass() != o.getClass()) {
return false;
}
Box box = (Box) o;
// otherwise same category and exactly same list (including ordering)
return category.equals(box.category) && partsInBox.equals(box.partsInBox);
}
}
// ------- Create a wrapper class around Box, repainting the house
class WrappedBox {
final Box box;
WrappedBox(Box box) {
assert box != null;
this.box = box;
}
public String getCategory() {
return box.category;
}
public List<Integer> getPartsInBox() {
return box.partsInBox;
}
public boolean equals(Object o) {
// same instance, then true (works if null passed, too)
if (this == o) {
return true;
}
// Null and not same class, then false
if (o == null || !(o instanceof WrappedBox)) {
return false;
}
//
// otherwise same category and the set of b1 parts is a superset of the set of b2 parts
// this is not symmetric; should probably be a set comparison. What happens if there
// are several integers with the same value??
// return b1.category.equals(b2.category)
// && b1.partsInBox.containsAll(b2.partsInBox);
//
// SO RECODE AS AUXILIARY EXERCISE:
//
WrappedBox other = (WrappedBox)o;
if (!this.getCategory().equals(other.getCategory())) {
return false;
}
//
// You probably want to buffer these somehow:
//
List<Integer> x1 = new ArrayList(this.getPartsInBox());
List<Integer> x2 = new ArrayList(other.getPartsInBox());
Collections.sort(x1);
Collections.sort(x2);
return x1.equals(x2);
}
}
// --------- Now we can ask for "contains", though one should really create a
// ---------- List<WrappedBox> first if this happens often
class BoxHandler {
static boolean containsBox(List<Box> boxes, Box box) {
assert box != null;
assert boxes != null;
WrappedBox wbox = new WrappedBox(box);
for (Box cur : boxes) {
if (wbox.equals(new WrappedBox(cur))) {
return true;
}
}
return false;
}
}
You can't provide other method to make the comparation to the List. The best and most simple solution is to modify your equals() method. If you can't modify equals you can implement a Decorator class to create a list with the areEquals comparation that you need.
public class BoxList<E extends Box> implements List<E>{
private List<E> list;
public BoxList(List<E> list) {
this.list = list;
}
//Modify the behavior of the methods
#Override
public boolean contains(Object o) {
for(E element : list) {
if (element.areEquals(o)) {
return true;
}
}
return false;
}
// Redirect all other List methods to the original list
#Override
public boolean add(E e) {
return list.add(e);
}
#Override
public void add(int index, E element) {
list.add(index, element);
}
...

Categories

Resources