i have a problem with checking equality of two arraylists in JUnit tests. When i test equality of two lists, it only checks if their string representation is the same. It works for simple examples, like [1,2,3],[1,2,3] or when list contains objects that are string-represented with all of their properties. But when i have two lists that have same string representation but some objects have different properties how do i check their equality?
This is the example:
If i have Object of Class Human(int height, int weight, boolean alive), and toString() method is:
public static String toString() {
return this.height + "-" + this.weight;
}
And i have two lists [20-30] and [20-30] but the object in first have
boolean alive = false
and in second
boolean alive = true
how to tell the compiler that lists are not equal? Sorry for confusing explanation and thank you in advance!!! :D
You can use Assert.class
assertArrayEquals(Object[] expecteds, Object[] actuals)
See http://junit.org/junit4/javadoc/4.8/org/junit/Assert.html
The equals-Methode of your Object have to compare all necessary attributes.
The (imho) most readable way to compare lists:
assertThat(actualitems, is(expectedItems));
using assertThat() and the hamcrest is() matcher (see here for further reading).
And in order to make that work: you have to implement equals() (and as consequence hashCode() on your class (see here for how to do that).
In other words: if you want that such fields take part when comparing two objects, than you need to express that by making that "field by field" comparison part of an #Override equals() implementation. Any decent IDE can generate those methods for you - but when learning Java, it is a good exercise to do it yourself a few times.
You need to override the hashcode and equals method. Here is the code
The output is
true
false
public class test {
public static void main(String[] args) {
Human rob = new Human(110, 100, false);
Human bob = new Human(110, 100, true);
Human tob = new Human(110, 100, false);
System.out.println(rob.equals(tob));
System.out.println(rob.equals(bob));
}
}
class Human {
int height;
int weight;
boolean alive;
public Human(int height, int weight, boolean alive) {
super();
this.height = height;
this.weight = weight;
this.alive = alive;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (alive ? 1231 : 1237);
result = prime * result + height;
result = prime * result + weight;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Human other = (Human) obj;
if (alive != other.alive)
return false;
if (height != other.height)
return false;
if (weight != other.weight)
return false;
return true;
}
#Override
public String toString() {
return "Human [height=" + height + ", weight=" + weight + "]";
}
}
A simple way would be
assertTrue("check equality", Arrays.equals(list1.toArray(), list2.toArray());
Only disadvantage is that you only get the information that they aren't equal but not where in the array the inequality happens.
Related
I'm currently looking through two very large lists of Peak Objects, by overriding the equals method and looping through the two lists, comparing every peak to every other peak. Is there a more efficient way of doing this? My lists can be ~10,000 elements, which means up to 10000 * 10000 comparisons.
The code for my peak object:
public class Peak extends Object{
private final SimpleIntegerProperty peakStart;
private final SimpleIntegerProperty peakEnd;
private final SimpleIntegerProperty peakMaxima;
private final SimpleIntegerProperty peakHeight;
private final SimpleIntegerProperty peakWidth;
private final SimpleStringProperty rname;
public Peak(int peakStart, int peakEnd, int peakMaxima, int peakHeight, String rname) {
this.peakStart = new SimpleIntegerProperty(peakStart);
this.peakEnd = new SimpleIntegerProperty(peakEnd);
this.peakMaxima = new SimpleIntegerProperty(peakMaxima);
this.peakHeight = new SimpleIntegerProperty(peakHeight);
this.peakWidth = new SimpleIntegerProperty(peakEnd - peakStart);
this.rname = new SimpleStringProperty(rname);
}
public String getRname() {
return rname.get();
}
public SimpleStringProperty rnameProperty() {
return rname;
}
public int getPeakWidth() {
return peakWidth.get();
}
public int getPeakHeight() {
return peakHeight.get();
}
public int getPeakStart() {
return peakStart.get();
}
public int getPeakEnd() {
return peakEnd.get();
}
public int getPeakMaxima() {
return peakMaxima.get();
}
#Override
public String toString() {
return "Peak{" +
"peakStart= " + peakStart.get() +
", peakEnd= " + peakEnd.get() +
", peakHeight= " + peakHeight.get() +
", rname= " + rname.get() +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Peak peak = (Peak) o;
if (!peakMaxima.equals(peak.peakMaxima)) return false;
return rname.equals(peak.rname);
}
#Override
public int hashCode() {
int result = peakMaxima.hashCode();
result = 31 * result + rname.hashCode();
return result;
}
}
And my loop for comparing the objects is here.
List<Peak> interestingPeaks = new ArrayList<>();
if(peakListOne != null && peakListTwo != null){
for(Peak peak : peakListOne){
for(Peak peak2 : peakListTwo){
if(peak.equals(peak2)){ //number one, check the rnames match
if((peak2.getPeakHeight() / peak.getPeakHeight() >= 9) || (peak.getPeakHeight() / peak2.getPeakHeight() >= 9)){
interestingPeaks.add(peak);
}
}
}
}
}
return interestingPeaks;
The code is basically matching the position of the maxima, and the rname , which is just a String. Then appending the peak to the interestingPeaks list if the height of one is a factor of 9x larger than the other.
Appreciate that if the two lists were sorted by maxima and name, you could simply make a single linear pass down both lists, and compare items side by side. If the two lists were in fact completely equal, then you would never find a pair from the two lists which were not equal.
List<Peak> p1;
List<Peak> p2;
p1.sort((p1, p2) -> {
int comp = Integer.compare(p1.getPeakMaxima(), p2.getPeakMaxima());
return comp != 0 ? comp : p1.getRname().compareTo(p2.getRname());
});
// and also sort the second list
Now we can just walk down both lists and check for a comparison failure:
for (int i=0; i < p1.size(); ++i) {
if (!p1.get(i).equals(p2.get(i))) {
System.out.println("peaks are not equal");
break;
}
}
This reduces an O(N^2) operation to one which is O(N*lgN), which is the penalty for doing both sorts (the final walk down the list is O(N), and would be negligible with either approach).
The equals() method should check if the dimensions of the first box and the cube are the same. How to fix it? It currently does not work.
The program returns the message "illegal start of type" at if. I am new to this plz help
public class testNew
{
public static void main (String []args)
{
Rectangle3 one = new Rectangle3(5,20);
Box3 two = new Box3(4,4,4);
Box3 three = new Box3(4,10,5);
Cube3 four = new Cube3(4,4,4);
showEffectBoth(one);
showEffectBoth(two);
showEffectBoth(three);
showEffectBoth(four);
}
public static String showEffectBoth(Rectangle3 r)
{
return System.out.println(r);
}
boolean b = two.equals(four);
if (b == true)
{
System.out.println("Box and cube have the same dimensions");
}
}
public class Rectangle3
{
// instance variables
int length;
int width;
public Rectangle3(int l, int w)
{
length = l;
width = w;
}
public int getLength()
{
return length;
}
public int getWidth()
{
return width;
}
public String toString()
{
return getClass().getName() + " - " + length + " X " + width;
}
public boolean equals(Rectangle3 obj)
{
if ((getLength().equals(obj.getLength()) && getWidth().equals(obj.getWidth())))
return true;
else
return false;
}
}
First, regarding the compiler error you have, it has nothing to do with the equals() method. It's only because all of the code below, should be inside your main method as it's the only part where you are declaring the variablestwo and four:
boolean b = two.equals(four);
if (b == true) {
System.out.println("Box and cube have the same dimensions");
}
Notice also, that the Rectangle3 class shouldn't be in the same file as testNew as both are declared public, if you want to use both of them in the same file then you need to remove the public declration from one of them (the one you will not use as filename)
Second, your equals() method is technically correct (I guess functionally as well) but it's not the equals() method you included in your code here, because this one belong to Rectangle3 while the equals() you are testing here should be defined in Box3 and Cube3
NB: Please notice as per assylias's comment, that because b is a boolean there is no need to use if (b == true), just if (b) will be sufficient
It is not the equals function. The line
boolean b = two.equals(four)
Is illegal. It is not within any method and it references variables declared in main()!
Hi I have this method which I created. Its job is to receive an Integer A, which can either be 10 or 30. It is meant to return TRUE if the value is ten, and false otherwise.
public static boolean checkStatus(int a){
if(a.equals(10)){
return true;
}
return false;
}
For some reason I am getting a compilation error in the if(a.equals(10)) condition, which says INT CANNOT BE DEREFERNCED. If I'm not mistaken, isn't the .equals() method the way to go in this circumstance?
Thanks for your help!
Primitives in Java (int, long, float, etc..) don't have member methods, so the call
if (a.equals(10))
will not compile, as you're trying to de-reference a primitive. Instead, you want to use the == operator to compare primitive values:
if (a == 10)
and reserve the use of the equals() method for non-primitive Objects
You can use equals for objects but an int is a primitive type (a), rather than an object.
Hence you need something like:
public static boolean checkStatus (int a) {
if (a == 10)
return true;
return false;
}
or the shorter and more sensible (in this case):
public static boolean checkStatus (int a) {
return (a == 10);
}
(a) The purists will argue this is proof that Java is not really an object-oriented language, but that's because they're raving loonies :-)
You can use
public static boolean checkStatus(int a){
if(a==10){
return true;
}
return false;
}
or
public static boolean checkStatus(Integer a){
if(a.equals(new Integer(10))){
return true;
}
return false;
}
equals() method belongs to Object class of Java and it has to override each and every Object classes like String, Integer and MyObject(implemented class). But int is not a Java Object and there is no equals() method there.
you can just use == with int values and you can simplify your code as bellow.
public static boolean checkStatus(int a){
return a==10;
}
equals is used for non-primitives basically for Objects.
== is used for primitives.
So, you can use it
public static boolean checkStatus (int a) {
if (a == 10)
return true;
return false;
}
Example 1:
For object, if equals method are overridden, then "equals" method will return true.
public class Employee {
int id;
#Override
public boolean equals(Object obj) {
Employee e = (Employee) obj;
return id == e.id;
}
Employee(int id) {
this.id = id;
}
public static void main(String[] args) {
Employee e1 = new Employee(5);
Employee e2 = new Employee(5);
System.out.println("e1.equals(e2) is: " + e1.equals(e2));
System.out.println("(e1 == e2) is: " + (e1 == e2));
}
}
Output:
e1.equals(e2) is: true
(e1 == e2) is: false
Example 2:
For object, if equals method are not overridden, then "equals" method works as "=="
public class Employee {
int id;
Employee(int id) {
this.id = id;
}
public static void main(String[] args) {
Employee e1 = new Employee(5);
Employee e2 = new Employee(5);
System.out.println("e1.equals(e2) is: " + e1.equals(e2));
System.out.println("(e1 == e2) is: " + (e1 == e2));
}
}
Output:
e1.equals(e2) is: false
(e1 == e2) is: false
Here "equals" method works as "==". So, don't forget to override the equals method for object.
int is a primitive in Java and primitives does not have behaviours a.k.a methods.
hence you cannot call .equals on int. So the options here are to use a ==
public static boolean checkStatus(Integer a){
return (a==10);
}
or convert the int to Integer which is a wrapper class
public static boolean checkStatus(Integer a){
return a.equals(10);
}
You can do something like this with Integer Class
Integer x = 5;
Integer y = 10;
Integer z =5;
Short a = 5;
System.out.println(x.equals(y));
System.out.println(x.equals(z));
System.out.println(x.equals(a));
Output:
false
true
false
You can of course wrap the integer up as :
Integer i = new Integer(a);
Then the equals function can be used with 'i', the new Integer object.
I have a class exactly like this:
public class Operator {
private String oper;
private boolean ltr;
private int pc;
//Ignore these methods...
public Operator(String t,int prc,boolean as) {oper=t;pc=-prc;ltr=as;}
public int precedence() {return pc;}
public boolean associativity() {return ltr;}
public String getName() {return oper;}
public int hashCode() {
int hash = 3;
hash = 19 * hash + (this.oper != null ? this.oper.hashCode() : 0);
hash = 19 * hash + (this.ltr ? 1 : 0);
hash = 19 * hash + this.pc;
return hash;
}
public boolean equals(Object o){
if (o instanceof String){
return oper.equals(o);
}
return false;
}
public String toString(){
return oper;
}
}
when I do: System.out.println(new Operator("+",4,true).equals("+")); it prints true, which means that equals method is working.
but when I do this:
Vector oprs = new Vector();
oprs.addElement(new Operator("+",4,true));
int iof = oprs.indexOf("+");
System.out.println(iof);
iof is -1. Manual searching finds it well, and System.out.println(oprs.elementAt(0)); prints +. I thought indexOf uses equals method to find the element (like in Java SE) so why on earth oprs.indexOf isn't working?
The type of "+" is String. You can't redefine equality for the String class so your equals method is not reflexive. Check out the Comparator class. It (and the collection classes that use it) might help you.
This question already has answers here:
Why can't we use '==' to compare two float or double numbers [duplicate]
(3 answers)
Closed 6 years ago.
I have this class
public class Point {
private Double[] coordinates;
private int dimension;
public Point(Double[] coordinates) {
dimension = coordinates.length;
this.coordinates = new Double[dimension];
for(int i = 0; i < dimension; i++)
this.coordinates[i] = coordinates[i];
}
public Double getCoord(int n) {
if(n < 0 || n > dimension -1 ){
throw new RuntimeException("error de coordenadas");
}
return coordinates[n];
}
public int getDim() {
return dimension;
}
public boolean equals(Object p1){
if( (p1 instanceof Point) ){
Point p = (Point) p1;
int n = p.getDim();
if(getDim() == n)
{
for(; n > 0; n--)
{
if( Double.valueOf(this.getCoord(n-1)) != Double.valueOf(p.getCoord(n-1)) ) // <------- BAD LINE!
{
System.out.println("Checking coord " + (n-1));
System.out.println("Coord " + (n-1) + " p = " + Double.valueOf(this.getCoord(n-1)));
System.out.println("Coord " + (n-1) + " p2 = " + Double.valueOf(p.getCoord(n-1)));
return false;
}
}
}
return true;
}
return false;
}
}
And this main
public class FigureTest {
public static void main(String[] args){
Double[] coord1 = {2.0,3.3};
Double[] coord2 = {2.0,3.3};
Point p = new Point(coord1);
Point q = new Point(coord2);
System.out.println(p.equals(q));
}
}
I can't understand why this p.equals(q) returns false! It goes inside the if( Double.valueOf(... but then prints that both coordinates are equal. It's the same if I remove the Double.valueOf. The only way it worked was when I put ! if(this.getCoord(n-1).equal(p.getCoord(n-1)), but I don't understand why the others don't work.
Double.valueOf returns a Double object, not a primitive double.
You perform a reference check (!=). So even if Double.valueOf(getCoords(n-1)) returned the same numeric value for both calls, different objects would be wrapping the numbers, so the != check would be true, causing your equals to return false.
Here's a quick example:
public static void main(String[] args){
System.out.println(Double.valueOf(5) == Double.valueOf(5));
}
Notice how it returns false. That's because == is a reference check, and a different object is being returned each time you call Double.valueOf. So when you do
Double.valueOf(...) != Double.valueOf(...)
That check will return true, since the valueOf calls didn't return the same object. This is why the check in your code returns true, resulting in equals returning false.
To fix this, you could...
Change your != check into a .equals check, which will compare the numeric values rather than the references.
Double.valueOf(...).equals(Double.valueOf(...));
This returns true if both share the same numeric value.
Or you could use doubleValue() when you call getCoord:
getCoord(n-1).doubleValue() != other.getCoord(n-1).doubleValue()
This will avoid the excess creation of Double objects.
In order to this to work;:
p.equals(q)
you need to keep the contract between Hashcode and equals and override properly both of them: equals AND hashcode in the class Point, and when I write properly I mean specifically this:
Please refer to this question if you dont know why or that you dont need it
Double.valueOf(this.getCoord(n-1)) != Double.valueOf(p.getCoord(n-1))
if the members of the class Point are doubles, then you are right when you compare those doubles as criteria to decide if p1.equals(p2)
but according to the documentation of the class Double, the static method Double.compare(this.getCoord(n-1)),p.getCoord(n-1) must be use in order to compare 2 doubles content.
hence I recommend to do in the equals method some similar to this
if( Double.compare(this.getCoord(n-1)),p.getCoord(n-1)!=0) )