I have a problem using Arraylists in java my code looks something like this:
List<Integer> numbers1 = new ArrayList<>();
List<Integer> numbers2 = new ArrayList<>();
boolean bcompare;
I add to the lists the same numbers, but when i try to compare the numbers of the index 0 of the lists like this the result of the boolean is false when it should be true:
bcompare = numbers1.get(0)==numbers2.get(0);
bcompare is false
But here is the thing when I use some temp variables and then compare them it gives me what i expected, a true value on bcompare:
int a=numbers1.get(0);
int b=numbers2.get(0);
bcompare = a==b;
bcompare is true
What am I doing wrong here?
It is cause you use the wrapper classes Integer. So an == compares the "references".
Use the equals() method instead to compare values of objects:
bcompare = numbers1.get(0).equals(numbers2.get(0));
The second comparison is true, because a int is a primitive type and contains only the value.
Have a look at http://mindprod.com/jgloss/intvsinteger.html for more details about the difference between int and Integer
When compare the results of get, you are comparing Integers. Using ==, this will compare the two object references to see if they are the same reference. With the exception of Integer caching, this will be false.
When you first assign the numbers to int, Java unboxes the Integer to int, so that == can compare the primitive values directly. This works as you intended.
Use the last code which uses int values.
return type of get() method is Object so when you are comparing like this
bcompare = numbers1.get(0).equals(numbers2.get(0));
It compares the reference of two different object so giving false.
either use equals() method or downcast it to the Integer class.
Using equals() method is good idea out of these both.
As,others have already said bcompare = numbers1.get(0)==numbers2.get(0); compares references of 2 Integer objects (which are not same, so, it will be false). int a=numbers1.get(0); extracts the int value from Integers ( by calling integer.intValue() implicitly) and compares them so, a==b; will be true.
Byte code :
public static void main(java.lang.String[]);
*** some code here***
30: if_acmpne 37 // byte code instruction to compare references
49: invokevirtual #27 // Method java/lang/Integer.intValue:()I
*** some other code here **
Related
To my understanding, the following code should print true, since both elements are equal.
From java docs Array.get() will return:
Returns the value of the indexed component in the specified array
object. The value is automatically wrapped in an object if it has a
primitive type.
However, when I run the following code it is printing
false:
public class Test1 {
static boolean equalTest(Object array1, Object array2) {
return Array.get(array1, 0).equals(Array.get(array2, 0));
}
public static void main(String[] args) {
int[] a = new int[1];
byte[] b = new byte[1];
a[0] = 3;
b[0] = 3;
System.out.println(equalTest(a, b));
}
}
My question is isn't classes implementing Number are or should be directly comparable to one another.
This has nothing to do with arrays really. Your comparison is equivalent to:
Object x = Integer.valueOf(3);
Object y = Byte.valueOf((byte) 3);
boolean equal = x.equals(y);
That's never going to return true.
Even though your original arrays are of the primitive types, Array.get returns Object, so you're getting the boxed types - and comparing values of those different types.
According to the documentation of Array.get(Object array,int index) method, the value returned is automatically wrapped in an object if it has a primitive type. So, if you add the following lines:
System.out.println(Array.get(array1, 0).getClass());
System.out.println(Array.get(array2, 0).getClass());
you will see the output is
class java.lang.Integer
class java.lang.Byte
The equals method of Integer class first of all checks if the object it is being compared to is also an instance of Integer, if not , then no further checks are required, they are not equal.
That's the reason you see the output is false as the objects being compared for equality are Integer and Byte.
The Array.get invocations return Integer and Byte object instances. These are not equal according to Integer.equals because the class type differs.
The problem is that the Array.get() method returns an object, so for int it'll return Integer, and for byte, it will return Byte. So .equals() method will return false because it first sees whether the type is the same, and then compares the values.
The array data types don't match. One is int and the other is byte. Since they're being passed to the function as Objects, they'll end up being Integer and Byte. So in order to compare them properly, you need to type-cast them to the same type. Something like:
static boolean equalTest(Object array1, Object array2) {
int int1 = (int) Array.get(array1, 0);
int int2 = (int) Array.get(array2, 0);
return int1.equals(int2);
// OR return int1 == int2;
}
If you look at the JavaDoc for Array.get you'll see:
The value is automatically wrapped in an object if it has a primitive
type.
So your bytes become Bytes and your ints become Integers.
That means the function you're calling is Integer.equals(Object)
This is implemented like so:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
You're not passing it an Integer, you're passing it a Byte so that's why it returns false.
This question already has answers here:
Java: Integer equals vs. ==
(7 answers)
Closed 7 years ago.
I got an exception
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeCollapse(TimSort.java:408)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at Main.main(Main.java:64)
when using this code :
Arrays.sort(arr, new Comparator<Integer[]>(){ //arr is 2D array
public int compare(Integer[] o1, Integer[] o2){
return o1[2]==o2[2]?0:o1[2]>o2[2]?1:-1;
}
});
which I believe is related to not satisfying transitivity of comparison, but when I made a little change like this :
Arrays.sort(arr, new Comparator<Integer[]>(){ //arr is 2D array
public int compare(Integer[] o1, Integer[] o2){
return o1[2].compareTo(o2[2]); // here is the change
}
});
the exception is no longer generated.
I can't understand an explanation of this issue as I'm sure that the Integer instance can be compared using relational operators (>, <, =) besides compareTo() method
Integer x = 1;
Integer y = 2;
System.out.println(x<y);
prints true as expected
can any body clarify ?
The problem is with:
o1[2]==o2[2]
This is comparing the Integers for identity. Equal instances are not necessarily identical. For example:
Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a == b); // False, instances are not identical.
System.out.println(a.equals(b)); // True, instances are equal.
It should be:
o1[2].equals(o2[2])
Or, to handle o1[2] being null:
Objects.equal(o1[2], o2[2])
since you are using Integer and not int, this is not valid:
o1[2]==o2[2]?0:o1[2]>o2[2]?1:-1;
you need to use equals or compareTo, not ==
The array you are sorting is made up of Integer objects. These are different than just plain old integers.
A plain old integer is just a number sitting in memory.
An Integer object is a an instance of a class that fills the same role as a basic integer, but also has a bunch of methods and data associated with it. That's the difference between being a piece of data or being an object.
The == operator compares numbers in memory. In the case of an instance of an object, it will compare the locations in memory, not the values of the numbers as you intend.
For Integer (and other number-like) objects, you must use the compareTo() method instead.
Your solution here is to either use the compareTo() method as suggested, or change your array to plain old integers.
You could also leave it as Integer objects and then use the Integer.intValue() to get a plain old integer returned, and then you can use the == comparison. But that's quite convoluted, IMO.
I made an Interval class with the following fields:
...
private static final Integer MINF = Integer.MIN_VALUE;
Integer head,tail;
...
when I make an instance of this class, making this.head = Integer.MIN_VALUE, and I want to check if the value of head is equal to MINF, it says that they aren't equal.
Interval i = new Interval(Integer.MIN_VALUE,10);
System.out.println(i.toString()); //[-2147483648,10]
So I went ahead and tried to print the values,
public String toString() {
...
//What the hell?
System.out.println("MINF == Integer.MIN_VALUE: " + (MINF == Integer.MIN_VALUE)); //true
System.out.println("MINF == this.head: " + (MINF == this.head)); //false
System.out.println("Integer.MIN_VALUE == this.head: " + (Integer.MIN_VALUE == this.head)); //true
...
return "*insert interval in format*";
}
Which says
MINF == Integer.MIN_VALUE is true
MINF == this.head is false, although this.head = -2147483648
Integer.MIN_VALUE == this.head is true
Am I missing something for why the second one is false?
Integer is the wrapping class, child of Object and containing an int value.
If you use only the primitive type int, == does a numerical comparison and not an object address comparison.
Mind that Integer.MIN_VALUE of course is an int too.
You are missing the fact that when stored in Integer (that is, you store Integer.MIN_VALUE in two different integers) and using == between them, the comparison is not of the values, but of the objects.
The objects are not identical because they are two different objects.
When each object is compared to Integer.MIN_VALUE, since Integer.MIN_VALUE is an int, the object is autounboxed and compared using int comparison.
No one here has addressed the REASON why they're different objects. Obviously:
System.out.println(new Integer(10) == new Integer(10));
outputs false, for reasons that have been discussed to death in the other answers to this question and in Comparing Integer objects
But, why is that happening here? You don't appear to be calling new Integer. The reason is that:
Integer.MIN_VALUE returns an int, not an Integer.
You have defined MINF to be an Integer
Autoboxing uses valueOf. See Does autoboxing call valueOf()?
valueOf calls new Integer if the int is not in the integer cache,
The cache is only the values -128 -> 127 inclusive.
And that is why you are seeing the "two Integer objects are not == behavior", because of autoboxing. Autoboxing is also why equality does not appear to be transitive here.
You can fix this problem by instead using:
private static final int MINF = Integer.MIN_VALUE;
And, in general: don't use Integer for simple fields.; only use it as a generic type where you actually need the object.
You are using Integer objects. The use of == should be used as a comparison of individual primitive's values only. Since you used the Integer class rather than the primitive int then it is comparing the object's references between the two variables rather than their values.
Because MINF is a separate object to head you are receiving false for a direct comparison using ==.
i am very very new to Java and i would like to know how can i compare 2 integers? I know == gets the job done.. but what about equals? Can this compare 2 integers? (when i say integers i mean "int" not "Integer").
My code is:
import java.lang.*;
import java.util.Scanner;
//i read 2 integers the first_int and second_int
//Code above
if(first_int.equals(second_int)){
//do smth
}
//Other Code
but for some reason this does not work.. i mean the Netbeans gives me an error: "int cannot be dereferenced" Why?
int is a primitive. You can use the wrapper Integer like
Integer first_int = 1;
Integer second_int = 1;
if(first_int.equals(second_int)){ // <-- Integer is a wrapper.
or you can compare by value (since it is a primitive type) like
int first_int = 1;
int second_int = 1;
if(first_int == second_int){ // <-- int is a primitive.
JLS-4.1. The Kinds of Types and Values says (in part)
There are two kinds of types in the Java programming language: primitive types (§4.2) and reference types (§4.3). There are, correspondingly, two kinds of data values that can be stored in variables, passed as arguments, returned by methods, and operated on: primitive values (§4.2) and reference values (§4.3).
If you want to compare between
1-two integer
If(5==5)
2- char
If('m'=='M')
3 string
String word="word"
word.equals("word")
int is primitive type.This itself having value but Integer is object and it is having primitive int type inside to hold the value.
You can do more operations like compare,longValue,..more by Using wrapper Integer.
== for Integer will not work the rang above -128 and 127. Integer hold cache value upto this range only in memory. More than this range you have to equals() method only to check Integer wrapper class.
equals() method will check the value stored in the reference location.
As int is primitive you can not use equals.
What you can do
Use Interger as wrapper
void IntEquals(Integer original, Integer reverse) {
Integer origianlNumber = original;
Integer reverseNumber = reverse;
if (origianlNumber.equals(reverse)) {
System.out.println("Equals ");
} else {
System.out.println("Not Equal");
}
Integer i1= new Integer(9);
Integer i2= new Integer(9);
if(i1==i2){
System.out.println("true");
}else{
System.out.println("false");
}
int i3=9;
int i4=9;
if(i3==i4){
System.out.println("true");
}else{
System.out.println("false");
}
if(i3==i2){
System.out.println("true");
}else{
System.out.println("false");
}
In Above Code First if-else print false, Why ?.But when second Return true and also third have true.I think wrapper classes(Like double,boolean,char)cant compare True ?
First if-else print false. Why?
== checks if the two references are referring to the same object, in this case they are not so the == check is false. You need to use Integer.equals(), not ==:
if (i1.equals(i2){
System.out.println("true");
}else{
System.out.println("false");
}
Second return true
== is correct to use for primitives: int is a primitive.
third have true
As pointed out by JB Nizet i2 is unboxed to an int which makes the if condition a check between two int primitives.
When == is used to compare references to objects, it returns true only if both references point to the same object.
In the first case, you have two different objects.
In the second case, you're not comparing objects, but primitive types.
In the third case, the Integer object is unboxed to its primitive int value to be compared with the primitive value, so two primitive values are compared.
You should never use == to compare objects, except for enums. Always use .equals().
Whenever you use "==", you are doing a object reference check. That means, the first check will fail since they are 2 different objects.
In the second case, its straight forward.
In the third case, the compiler autoboxes "i2". So, the comparison will work fine.
Remember you are not comparing 2 primitives but 2 Objects.. so Use .equals() method..
The variables i1 and i2 refer to Objects, not primitive types. Using the == operator on objects in Java checks that the references are equal, if you want to compare them you should use the .equals() method.
The comparison of i3 and i2 returns true because you're comparing a primitive type (the int i3) with a wrapper class for that primitive type (the Integer i2), so Java unboxes the value of i2 to an int and then compares them (which does work with the == operator).
in first if - you are compare two objects - thay are different. Result = false
in second - you are compare two int values. Result true
in therd - you are compare int and Integer, after unboxing you have two int. Result - true.
for Integer use equals.
The first case, JVM checks whether both i1 and i2 are same reference or not. As they are different so it results false.
The second case, it's no problem as both are primitive data types and have same value, so it's true.
In third case, i2 is first autounboxed and then comparision takes place, so it results true.
With the autocast, (int)i1==(int)i2 will return true, so will (i1==i4)
As the other comments explained it, == only compares the objects (which references are passed by value)
another "safe" and alternative way is using the modulo operation
if ( ( i3%i4)==0) System.out.println("true");