Code segment on arrays java [duplicate] - java

This question already has answers here:
How does an array's equal method work?
(5 answers)
Closed 8 years ago.
So I was doing review, and came across this question that I'm not very sure about.
Consider the following code segment:
int[] A = {1,2,3};
int[] B = {1,2,3};
int[] C = A;
After this code executes, which of the following expressions would evaluate to true?
I. A.equals (B)
II. A == B
III. A ==C
I only
II only
III only
I and III only
I, II, and III
I thought it was I only, but one of my classmates said that it was III only.
Could some please explain this?
Thanks for the help.

The answer is in the above linked question by #J L:
Arrays.equals(array1, array2) works as you would expect (i.e. compares
content), array1.equals(array2) falls back to Object.equals
implementation, which in turn compares identity, and thus better
replaced by == (for purists: yes I know about null).
Simply put, you are setting C equal to A, so that's why A == C is true. You performing an Object.equals essentially. While it appears on the surface that A.equals(B) would be true, they are not because of the internals behind Object.equals.
So your friend is right.

The third has a and c pointing the same object. The others not.

Your friend is correct.
In the code you are saying C = A.
This means that C is the same exact object as A.
In other cases, they are not the same object, although they have the same content.
You might want to have a look at Arrays.deepEquals which returns true (your code is slightly modified):
package arrays;
import java.util.Arrays;
public class ArraysTest {
public static void main(String[] args) {
Integer[] A = { 1, 2, 3 };
Integer[] B = { 1, 2, 3 };
Integer[] C = A;
System.out.println("A.equals(B) is " + (A.equals(B)));
System.out.println("Arrays.deepEquals(A, B) is "
+ (Arrays.deepEquals(A, B)));
System.out.println("A == B is " + (A == B));
System.out.println("A == C is " + (A == C));
}
}
The output will be:
A.equals(B) is false
Arrays.deepEquals(a, b) is true
A == B is false
A == C is true

only the third one would be true.
take the first
int[] A = {1,2,3};
witch means A has position 0:1, position 1:2, position 2:3.
then take the second
int[] B = {1,2,3};
witch means B has position 0:1, position 1:2, position 2:3.
so they have the same values in each position but they are two different int arrays
but then take the third
int[] C = A;
their you are saying `int[] C is equal to int[] A,
just like saying
String a = "LOL";
String b = a;
Also just a few notes, Only strings are compared by using .equalsanything else is compared using ==, and always use lower case letters for variables, it makes it easier to code.
you can always test methods with this
if(A.equals(B)
{
System.out.println("A.equals(B) is true");
}
else
{
System.out.println("A.equals(B) is false";
}
same for
if(A == B)
{
System.out.println("A == B is true");
}
else
{
System.out.println("A == B is false");
}
Hope this helps, Luke.

Related

Java Help: Determining if Digits Can Form a Sequence

I have a quick question on an assignment I'm trying to finish up. I'm writing a boolean method that takes three digit parameters (0-9) and returns true if they can be re arranged to make up a sequence. The hard part, for me at least, is that 0 can make a sequence with 8, 9, or 1,2. The three numbers are assumed to all be different. To be clear, the number 5,7,6 would be true because it can be rearranged to be 5, 6, 7, a sequence. Also 8,0,9 would return true, but 2,4,7 would not. I'm hoping someone can point me in the right direction with this, any help at all would be much appreciated!
You only need to check the validity of two tests:
Are all numbers different?
Is the absolute difference between the extremes 2?
This would give you the following method:
public static boolean isSequence(int a, int b, int c) {
if(a == 0) a = 10;
if(b == 0) b = 10;
if(c == 0) c = 10;
//Add the commented-out lines to make it safe to use with non-different numbers.
//boolean allDifferent = !(a == b) && !(b == c) && !(a == c);
boolean extremesIsTwo = Math.abs(Math.max(Math.max(a, b), c)
- Math.min(Math.min(a, b), c)) == 2;
//return allDifferent && extremesIsTwo;
return extremesIsTwo;
}
When you look at it, it's only a matter of simple logic, and finding the shortest path to the answer. There might be more optimized ways to do this, but this is clear, readable and works just fine.
Now, if you really want to get grinding on a problem of the like, you could either try to optimize this algorithm, or find another way to check that the three numbers are a sequence.
EDIT This version is scalable. And even though your requirements are for three arguments, I would still consider this solution, because it uses OOP to avoid repetition of code. As requested, it also doesn't check for duplicates.
public static boolean isSequenceScalable(List<Integer> list) {
list = list.stream().map(i -> i = (i == 0) ? 10 : i).collect(Collectors.toList());
list.sort(Integer::compareTo);
if (Math.abs(list.get(0) - list.get(list.size() - 1)) == 2) return true;
return false;
}

If a = b, what happens if each value changes respectively?

What happens if you change the variable b, or what if you change a. What does the order have to do with anything.
I know count = count + 1 but the two variables is messing up my brain.
b = 7;
a = 7;
a = b;
a += 1;
What happens to b?
What happens to b?
Nothing happens to b.
When you do
a = b;
you're copying the value stored in b and putting it in a. (You're not making a an alias of b.)
When you then do a += 1; you're changing the value stored in a (and the value stored in b remains unchanged).
You can verify this by printing the final values after your code snippet:
System.out.println(a); // prints 8
System.out.println(b); // prints 7
What happens if you change the variable b, or what if you change a. What does the order have to do with anything.
a and b are two independent variables and changing one will never affect the other.
The order matters since when you do a = b the value of b is copied into a and whatever a stored before is discarded. If you had done a += 1 prior to a = b, then a would have been restored to 7 again.
int is raw type you don't copy reference but the value itself. This will work same way for Integer because it is immutable class.
int b = 7;
int a = 7;
a = b;
a+=1;
System.out.println(a);// ->8
System.out.println(b);// ->7
Still 7.
integer is raw type and if you assign a int variable to another int, just its value is received by the new one. Not the object itself.
b stays 7.
a becomes 8.
You could use System.out.println(); to print values of variables and find out yourself if you ever doubt.
That or use the debugger.
public static void main(String[] args) {
int b = 7; // b points to 7
int a = 7; // a points to 7
a = b; // b and a points to 7
a += 1; // a points to 8 now, b is still pointing to 7
System.out.println(a);
System.out.println(b);
}
output
8
7
When we do a += 1; we change the value stored in a (value stored in b is still same).

Understanding do-while loop

I'm doing the oracle certified associate Java SE7 Programmer practice exams (the book) and came across a question, and I don't understand the answer even with the explanation.
Here's the explanation and the code:
It will print 3. The loop body is executed twice and the program will print 3.
I don't understand how the loop body is executed twice, maybe I don't understand what the b=!b means. Can someone explain please?
class TestClass {
public static void main(String args[]){
boolean b = false;
int i = 1;
do{
i + + ;
} while (b = !b);
System.out.println(i);
}
}
b = !b is an assignment which assigns the inverse of b to itself (effectively flipping between true and false)
in java, an assignment returns what was assigned (so that a=b=1 is possible)
therefore while (b=!b) will flip the value of b, and then check the value of b.
b=!b
Will always be true, why?
Because, what you are doing is that you insert to "b" the opposite value (T->F, F->T),and if there was no problem while (b = !b); will return TRUE....
So at your case while (b = !b); will always return true
Iteration 1
boolean b = false;
int i = 1;
do{
i++ ; // i = 2
} while (b = !b); // b = !false = true so one more execution
Iteration 2
do{
i++ ; // i = 3
} while (b = !b); // b = !true = false so loop breaks
So it will print 3. simple :)
Actually the confusion is with = sign. = is assigning operator where as == is the conditional operator. The first will assign the value whereas later will check for the condition. You can play with it and have some other result like
int a = 6;
int b = 10;
System.out.println(a = b);
System.out.println(a == b);
and you will get the idea.
At the end of the first iteration the variable i will be 2 because of the increment operator. The expression b=!b will result to true (b = !false) and set the variable b to true as well. So the loop gets executed again.
At the end of the second iteration the variable i is now 3. The expression b=!b will result to false (b = !true), which will be also the value of the variable b. So the whole do-while-loop terminates and the println() statement shows 3.
Keep in mind: = (assign operator) is not the same as == (equality check).
The condition
b = !b;
uses the assignment operator, which returns the value that has been assigned.
Initially, b is false, and therefore true is assigned to b, and used for the condition. The while loop therefore executes a second time. In this execution, b is true, and therefore false is assigned to b and used for the loop condition. The loop therefore exits.

How do I search for one array whose contents match another?

I have an ArrayList of int arrays that is returning false when I ask if it contains the specified coordinates. It does contain the coordinates I request so it should return TRUE.
Here's my code.
//debug code
for (int i = 0; i < Locations.size(); i++)
{
int[] TestLoc = Locations.get(i);
System.out.print(TestLoc[0] + " " + TestLoc[1] + " " + TestLoc[2] + " == " + Location[0] + " " + Location[1] + " " + Location[2] + "? - ");
if (Location == TestLoc)
{
System.out.println("TRUE");
}
else
{
System.out.println("FALSE");
}
}
//real code
if (Locations.contains(Location))
{
Locations.remove(Location);
}
else
{
System.out.println("FAIL");
}
And output, requesting the coordinates 57, 64, 105 when the list contains 4 coordinates.
56 64 105 == 57 64 105? - FALSE
56 64 106 == 57 64 105? - FALSE
56 64 107 == 57 64 105? - FALSE
57 64 105 == 57 64 105? - FALSE
What gives???
Java's arrays equals are identity equality. You need to create an actual Coordinate class.
Put another way:
int[] c1 = new int[] { 1, 2 };
int[] c2 = new int[] { 1, 2 };
System.out.println(c1.equals(c2)); // prints false
The best would be to get a data class, for instance Coordinate to store your data and override the equals method. Another option, if you just store phone numbers, could be to use strings to reprensent well formatted phone numbers, and the use the equals method of the String class.
Arrays in Java are objects.
When you use the == operator, you are comparing whether Location is the same array as Testloc, which it isn't. What you really want is to compare the values in each array to see if they are equal.
Rather than writing your own, you can use the Arrays.equals() static method to compare the two for equality.
The problem appears to be with the following line:
if (Location == TestLoc)
Presumably, TestLoc is is an array of integers, and Location is also bound to an array.
The test above will only return true if the TestLoc and Location variables both point to the same array instance, and will not return true if those two variables point to different array instances that both happen to have the same integers in the same positions. You're testing "reference equality" above—asking only if these two things are the same thing—as opposed to "value equality," which asks whether two things are equivalent, irrespective of whether they are represented as two distinct objects in the computer's memory space.
Some programming languages lack such a distinction, and some allow one to define new types that are better treated as values—where identity is immaterial—than as entities, where identity may be more important than any would-be value equivalence. Java uses a distinct method—Object#equals()—to query equivalence or value equality of Object instances, while the == operator always does just one thing: it evaluates value equality of any two things, even if those things are object references.
Hence, when comparing two array instances as you are here, both of which are some type of Object, the == operator asks not whether the two things pointed to by those references are equivalent, but rather whether the value of the references themselves are equivalent. If they happen to point to the same target object, they're equivalent, but if they don't, it doesn't matter whether the two distinct target objects would seem similar in value; == returns false because the two target objects are represented by distinct references.
By comparing the arrays with ==, you are checking to see if they are the same array. You would have to loop through each array and check TestLoc[i] == Location[i]. You might be able to use .equals(), I don't recall if java has .equals() for arrays
This works for me:
List<int[]> l = new ArrayList<int[]>();
l.add(new int[] {56, 64, 105});
l.add(new int[] {56, 64, 105});
l.add(new int[] {56, 64, 105});
for (int i = 0; i < l.size(); i++)
{
int[] t = l.get(i);
if (l.get(i) == t)
{
System.out.println("TRUE");
}
else
{
System.out.println("FALSE");
}
}

Why are these == but not `equals()`?

I'm a bit confused about the way Java treats == and equals() when it comes to int, Integer and other types of numbers. For example:
Integer X = 9000;
int x = 9000;
Short Y = 9000;
short y = 9000;
List<Boolean> results = new ArrayList<Boolean>();
// results.add(X == Y); DOES NOT COMPILE 1)
results.add(Y == 9000); // 2)
results.add(X == y); // 3)
results.add(X.equals(x)); // 4)
results.add(X.equals(Y)); // 5)
results.add(X.equals(y)); // 6)
System.out.println(results);
outputs (maybe you should make your guess first):
[true, true, true, false, false]
That X == Y does not compile is to be expected, being different objects.
I'm a little surprised that Y == 9 is true, given that 9 is by default an int, and given that 1) didn't even compile. Note that you can't put an int into a method expecting a Short, yet here they are equal.
This is surprising for the same reason as two, but it seems worse.
Not surprising, as x is autoboxed to and Integer.
Not surprising, as objects in different classes should not be equal().
What?? X == y is true but X.equals(y) is false? Shouldn't == always be stricter than equals()?
I'd appreciate it if anyone can help me make sense of this. For what reason do == and equals() behave this way?
Edit: I have changed 9 to 9000 to show that this behavior is not related to the any unusual ways that the integers from -128 to 127 behave.
2nd Edit: OK, if you think you understand this stuff, you should consider the following, just to make sure:
Integer X = 9000;
Integer Z = 9000;
short y = 9000;
List<Boolean> results = new ArrayList<Boolean>();
results.add(X == Z); // 1)
results.add(X == y); // 2)
results.add(X.equals(Z)); // 3)
results.add(X.equals(y)); // 4)
System.out.println(results);
outputs:
[false, true, true, false]
The reason, as best as I understand it:
Different instance, so different.
X unboxed, then same value, so equal.
Same value, so equal.
y cannot be boxed to an Integer so cannot be equal.
(small) Integer instances are cached, so the invariant x == y is holded for small instances (actually -127 +128, depends on JVM):
Integer a = 10;
Integer b = 10;
assert(a == b); // ok, same instance reused
a = 1024;
b = 1024;
assert(a == b); // fail, not the same instance....
assert(a.equals(b)); // but same _value_
EDIT
4) and 5) yield false because equals check types: X is an Integer whereas Y is a Short. This is the java.lang.Integer#equals method:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
The reason for
X == y
being true has to do with binary numeric promotion. When at least one operand to the equality operator is convertible to a numeric type, the numeric equality operator is used. First, the first operand is unboxed. Then, both operands are converted to int.
While
X.equals(y)
is a normal function call. As has been mentioned, y will be autoboxed to a Short object. Integer.equals always returns false if the argument is not an Integer instance. This can be easily seen by inspecting the implementation.
One could argue that this is a design flaw.
The morale of the story:
Autoboxing/unboxing is confusing, as is type promotion. Together, they make for good riddles but horrendous code.
In practice, it seldom makes sense to use numeric types smaller than int, and I'm almost inclined to configure my eclipse compiler to flag all autoboxing and -unboxing as an error.
Your problem here is not only how it treats == but autoboxing... When you compare Y and 9 you are comparing two primitives that are equal, in the last two cases you get false simply because that's how equals work. Two objects are equal only if they are of the same kind and have the same value.
When you say in "X.equals(y)" you are telling it to do Integer.equals(Short) and looking at the implementation of Integer.equals() it will fail:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Because of autoboxing the last two will result in the same failure as they will both be passed in as Shorts.
Edit: Forgot one thing... In the case of results.add(X == y); it will unbox X and do (X.intValue() == y) which happens to be true as well as 9 == 9
This automatic conversion is called autoboxing.
I remember a good practice for overriding "equal(object obj)" is of first checking the type of the parameter passed in. So perhap this causes X.equals(Y) to be false. You might check the souce code to dig out the truth :)
A bit more detail on how autoboxing works and how "small" valued Integer objects are cached:
When a primitive int is autoboxed into an Integer, the compiler does that by replacing the code with a call to Integer.valueOf(...). So, the following:
Integer a = 10;
is replaced by the compiler with the following:
Integer a = Integer.valueOf(10);
The valueOf(...) method of class Integer maintains a cache that contains Integer objects for all values between -127 and 128. If you call valueOf(...) with a value that's in this range, the method returns a pre-existing object from the cache. If the value is outside the range, it returns a new Integer object initialized with the specified value. (If you want to know exactly how it works, lookup the file src.zip in your JDK installation directory, and look for the source code of class java.lang.Integer in it.)
Now, if you do this:
Integer a = 10;
Integer b = 10;
System.out.println(a == b);
you'll see that true is printed - but not because a and b have the same value, but because a and b are referring to the same Integer object, the object from the cache returned by Integer.valueOf(...).
If you change the values:
Integer a = 200;
Integer b = 200;
System.out.println(a == b);
then false is printed, because 200 is outside the range of the cache, and so a and b refer to two distinct Integer objects.
It's unfortunate that == is used for object equality for value types such as the wrapper classes and String in Java - it's counter-intuitive.
Java will convert an Integer into an int automatically, if needed. Same applies to Short. This feature is called autoboxing and autounboxing. You can read about it here.
It means that when you run the code:
int a = 5;
Integer b = a;
System.out.println(a == b);
Java converts it into:
int a = 5;
Integer b = new Integer(a);
System.out.println(a == b.valueOf());

Categories