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");
}
}
Related
How strong is the hashing mechanism that is used in the Arrays.hashCode methods against collision? What is the possibility of two different arrays (of, say, double) to have an exact hash value calculated with these methods?
Arrays.hashCode(double[]) is specified to return the equivalent value of a List containing Double values representing the same numeric value.
List.hashCode in turn is specified with a fairly simple algorithm:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
In general the multiplication with a prime number is a good practice for general-purpose hash functions, but it's far from a cryptographically strong hash function.
This means that while collisions are unlikely in the general (effectively random) case, they can usually be constructed quite easily if you can influence (or select) the hashCode of the items in the List.
As a constructed example consider these two statements:
System.out.println(Arrays.hashCode(new double[] {4.753E-321d}));
System.out.println(Arrays.hashCode(new double[] {4.9E-324d, 4.9E-324d}));
Both of these will output 993, despite being clearly different arrays.
This is the implementation of Arrays.hashCode that you use
public static int hashCode(int a[]) {
if (a == null)
return 0;
int result = 1;
for (int element : a)
result = 31 * result + element;
return result;
}
If your values happen to be smaller then 31 they are treated like distinct numbers in the base 31, so each result in a different numbers (if we ignore overflows for now). Lets call those pure hashes
Now of course 31^11 is way larger then the number of integers in Java, so we will get tons of overflows. But since the powers of 31 and the maximum integer are "very different" you don't get a almost random distribution, but a very regular uniform distribution.
Lets consider a smaller example. I assume you have only 2 elements in your array and the range from 0 to 5 each. I try to create "hashCode" between 0 and 37 by taking the modulo 38 of the "pure hash" The result is that I get streaks of 5 integers with small gaps in between, and not a single collision.
val hashes = for {
i <- 0 to 4
j <- 0 to 4
} yield (i * 31 + j) % 38
enter code here
println(hashes.size) // prints 25
println(hashes.toSet.size) // prints 25
To verify if this is what happens to your numbers you might create a graph as follows: For each hash take the first 16 bits for x and and the second 16 bits for y, color that dot black. I bet you will see an extremely regular pattern.
I am a student learning Java and am stuck on the last part of a homework problem. I need to write a conditional statement that prints whether the roll of the dice was a Yahtzee or not (all five dice are equal to one another). I cannot figure out how to do this since I used ints and not boolean. I know I cannot cast an int into boolean and up to this point this casting is the only way I know how to change variables. Any help would be appreciated since the ways to achieve what I am looking for have been more than I can understand at this point.
This is what I have and the issue is in the second to last line.
import java.util.Random;
public class FiveDice_JLR
{
//-----------------------------------------------------------------
// Generates random numbers in various ranges.
//-----------------------------------------------------------------
public static void main(String[] args)
{
Random generator = new Random();
int die1, die2, die3, die4, die5;
die1 = generator.nextInt(6)+1;
System.out.println("Die 1: " + die1);
die2 = generator.nextInt(6)+1;
System.out.println("Die 2: " + die2);
die3 = generator.nextInt(6)+1;
System.out.println("Die 3: " + die3);
die4 = generator.nextInt(6)+1;
System.out.println("Die 4: " + die4);
die5 = generator.nextInt(6)+1;
System.out.println("Die 5: " + die5);
**if(die1==die2&==die3==die4&==die5&&);**
{
System.out.println("Yahtzee!!!!");
}
}
If you use just &, that is the bitwise AND, therefore it compares the bits of all the numbers. What you want is &&, which is logical AND:
if(die1 == die2 && die2 == die3 && die3 == die4 && die4 == die5) {
// Something here...
}
Also note that each && operator just like the == operator, requires 2 operands to properly compare
Assuming all your values are positive, another method to check if all numbers are equal to each other is to add them all up and check if the sum is equal to 5 times one of the values.
if((die1 + die2 + die3 + die4 + die5) == die1 * 5) {
// Something here...
}
This is doing the same thing and is shorter, but is prone to error because you may in the future decide to generate negative numbers (for some reason), or decide to use more dice and forget to change 5 to the appropriate number, etc. In general, just stick to the first one
There are two operators that will be important for checking that the values of all your dice are the same: the conditional AND operator (&&) and the equality operator (==). The Java documentation includes some good details of what these are, and how to use them.
There are a couple of things to keep in mind with these. Both of these operators are binary operators. They operate on two operands. e.g. a == b compares the value of a to b. Similarly, a && b evaluates to true if both a and b are true.
Of course, this presents a challenge when we want to compare the values of more than two operands. Say we have three variables, a, b, and c. How would we check that they all have the same value? (For simplicity, we'll assume they're all primitive types).
We know how to check that a and b are the same: a == b.
We also know how to check that b and c are the same: b == c.
If both of these are true then, by the transitive property of equality, we know that a must also be equal to c. How do we check two conditions within a single statement? Using the conditional AND operator, of course:
a == b && b == c
This was a simple example with just three variables, but this can be extended to any number of variables (say, to the values of 5 dice). Give it a try, and see if you can get it working using these two operators.
The statement you are looking for is
if(die1==die2 && die2==die3 && die3==die4 && die4==die5)
Or, for #smac89's and &duffymo's benefit, a version with &:
if(die1==die2 & die2==die3 & die3==die4 & die4==die5)
which will run slower because of fully evaluating everything, but is otherwise semantically identical.
My question is about java interning and constant pools.
Java maintains a a constants pool for java.lang.String, to use JVM memory cleverly, and to do so java.lang.String is made immutable. So why doesn't java maintain constant pools of other immutable types, such as Long, Integer, Char, Short ? Wouldn't that save memory too ?
I am aware of the fact that Integers are pooled for value range [-127, 127], though I do not understand the reason for choosing this range.
Here's a test code I wrote to test pooling of other immutable data types.
public class PoolTest {
public static void main(String... args) {
// Pooling of Integer [-127, 127]
Integer x = 127, y = 127;
System.out.println("Integer:" + (x == y)); // prints true
x = 129;
y = 129;
System.out.println("Integer:" + (x == y)); // prints false
// Apparent pooling of short [-127, 127]
Short i = 127, j = 127;
System.out.println("Short: " + (i == j)); // prints true
i = 128;
j = 128;
System.out.println("Short: " + (i == j)); // prints false
// No pooling of long values
Long k = 10L, l = 10L;
System.out.println("Long: " + (i == j)); // prints false
k = 128L;
l = 128L;
System.out.println("Long: " + (i == j)); // prints false
}
}
The purpose of a constant pool is to reduce the memory overhead required by keeping multiple copies of constants. In the case of Strings, the JVM is inherently required to keep some object around for each individually distinguishable constant, and the Java spec basically says that the JVM should deduplicate String objects when class loading. The ability to manually place Strings in the pool via intern is inexpensive and allows programmers to identify particular values (such as properties) that are going to be around for the life of the program and tell the JVM to put them out of the way of normal garbage collection.
Pooling numeric constants, on the other hand, doesn't make a lot of sense, for a few reasons:
Most particular numbers aren't ever used in a given program's code.
When numbers are used in code, embedding them in the code as immediate opcode values is less expensive in terms of memory than trying to pool them. Note that even the empty String carries around a char[], an int for its length, and another for its hashCode. For a number, by contrast, a maximum of eight immediate bytes is required.
As of recent Java versions, Byte, Short, and Integer objects from -128 to 127 (0 to 127 for Character) are precached for performance reasons, not to save memory. This range was presumably chosen because this is the ranged of a signed byte, and it will cover a large number of common uses, while it would be impractical to try to precache a very large number of values.
As a note, keep in mind that the rules about interning were made long before the introduction of autoboxing and generic types in Java 5, which significantly expanded how much the wrapper classes were casually used. This increase in use led Sun to add those common values to a constant pool.
Well, because String objects are immutable, it's safe for multiple references to "share" the same String object.
public class ImmutableStrings
{
public static void main(String[] args)
{
String one = "str1";
String two = "str1";
System.out.println(one.equals(two));
System.out.println(one == two);
}
}
// Output
true
true
In such a case, there is really no need to make two instances of an identical String object. If a String object could be changed, as a StringBuffer can be changed, we would be forced to create two separate objects. But, as we know that String objects cannot change, we can safely share a String object among the two String references, one and two. This is done through the String literal pool.
You can go through this link to know in details.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Inconsistent behavior on java's ==
Integer wrapper objects share the same instances only within the value 127?
I have found the following == behaviour for Integer objects and I fail to understand it. (I am well aware that one should use equals for such comparisons, but I am studying for OCPJP...)
On short, == works as expected for 1000, but not for 10.
The former fragment of code is:
Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2) System.out.println("different objects");
if(i1.equals(i2)) System.out.println("meaningfully equal");
and it behaves as one would expect:
different objects
meaningfully equal
The latter though:
Integer i3 = 10;
Integer i4 = 10;
if(i3 == i4) System.out.println("same object");
if(i3.equals(i4)) System.out.println("meaningfully equal");
has the following output:
same object
meaningfully equal
Can someone please explain why this is happening?
Since Java 5, wrapper class caching was introduced. The following is an examination of the cache created by an inner class, IntegerCache, located in the Integer cache. For example, the following code will create a cache:
Integer myNumber = 10
or
Integer myNumber = Integer.valueOf(10);
256 Integer objects are created in the range of -128 to 127 which are all stored in an Integer array. This caching functionality can be seen by looking at the inner class, IntegerCache, which is found in Integer:
So when creating an object using Integer.valueOf or directly assigning a value to an Integer within the range of -128 to 127 the same object will be returned. Therefore, consider the following example:
Integer i = 100;
Integer p = 100;
if (i == p)
System.out.println("i and p are the same.");
if (i != p)
System.out.println("i and p are different.");
if(i.equals(p))
System.out.println("i and p contain the same value.");
The output is:
i and p are the same.
i and p contain the same value.
It is important to note that object i and p only equate to true because they are the same object, the comparison is not based on the value, it is based on object equality. If Integer i and p are outside the range of -128 or 127 the cache is not used, therefore new objects are created. When doing a comparison for value always use the “.equals” method. It is also important to note that instantiating an Integer does not create this caching.
Remember that “==” is always used for object equality, it has not been overloaded for comparing unboxed values
See Integer wrapper objects share the same instances only within the value 127?. The Integer class keeps shared static instances around for common values.
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());