How to force eclipse to create different object references - java

i am trying to create all subsets of a set and group them without duplicates. For example, in a set like {1,2,3,4,5,6}, {(1,2), (3,4), (5,6)} this tuple can be valid on the other hand {(1,2), (2,4), (5,6)} this tuple shouldn't be valid since it has two instance of number 2 although the set has only one instance of number 2.
To guarantee this non-duplicate form, i have a small method that checks the given subset, if it has the number that is passed to the method as parameter, it returns true.
The problem with that, when there is duplicate in the set like {1,2,3,1,5,6} it shouldn't say that the second "1" is equal to first "1". To make this happen, i used "==" operator to compare the object references and i hoped that this will make difference between first "1" and the second "1", but it didn't. Apparently, Eclipse creates same object reference for same type of objects which is created in compile-time and have same value. How can i force Eclipse to create different object references ? If there is a way to flag objects with unique number, that helps also.
Here is the method:
private boolean doesTuplesHave(Integer number, ArrayList<ArrayList<Integer>> tuples){
for(ArrayList<Integer> list : tuples){
for(Integer numinTuple : list){
if( numinTuple == number){
return true;
}
}
}
return false;
}

a) Eclipse has nothing to do with it, this is standard behavior for all Java compilers and JVMs.
b) use .equals()
if(numinTuple.equals(number))
or, if it's possible that one of the sides can be null, use Objects.equals():
if(Objects.equals(numinTuple, number))
Explanation: in Java, the == operator checks reference equality, not semantic equality (i.e. is this the same object vs do these objects have the same value)
See: What is the difference between == vs equals() in Java?
Also, in Java 8, your method can be rewritten in a more concise way as:
return tuples.stream().anyMatch(l->l.contains(number));
(which also fixes your bug)

Related

Why does .contains(1) return false when called on a HashSet<Long> that contains 1l?

public static void main(String[] args) {
List<Long> list = Arrays.asList(1l,2l,3l);
Set<Long> set = new HashSet<>(list);
System.out.println(set); // [1, 2, 3]
System.out.println(set.contains(1)); // false
}
The set contains {1,2,3}, but when I call set.contains(1) it returns false. Why isn't 1 auto casted to 1l? I think it may be related to Java autoboxing and casting problem.
Because contains is defined, for legacy reasons, as contains(Object), not contains(T). The int 1, coerced to an object, is boxed as an Integer.
Comments have mentioned that because a long is not an int, the set will not contain it, but I believe there is a more concrete answer that can be given to this case specifically.
If we look into the HashSet source code, we find that its contains method falls back to a HashMap's containsKey method. Looking into that, we find that the fundamental check is this:
if (e.hash == hash && e.key.equals(key))
A simple check will verify that the two values will produce the same hash, but that the direct check below will fail.
new Integer(1).equals(new Long(1l));
This happens for the precise reason mentioned in the comments. When you use the Integer (or Long) equals() method, the very first thing that Java will do is check if the types are the same. It will not do any casting. The types are different, and so the result is false. To avoid this, cast your integer to a long before checking if the set contains it.
Note that this behavior is different from using a primitive-type comparison 1 == 1l. Java will not wrap these in objects and will not use the object .equals() method, so this evaluation is skipped. Casting happens and the result is true.

(Java) Comparing values of two variables in if-statement but can't use `.equals()`

(Heads up, I've never written a proper program before so bear with me)
I'm trying to write an if-statement that compares the VALUES of the position fields of two instances (which literally returns the integer "position"). Problem is, they are private fields in different classes so I cannot access them directly. Instead, I made methods in each class which return the variable.
Now in my if-statement, this is the condition that is to be true/false:
if (enemy1.getPosition() = player.getGun1Position())
Now the problem is, if I use = the machine assumes I'm trying to assign a value to the position of enemy1 and I've been researching to find that == compares the memory location rather than the value of the two fields.
I have also read that
.equals()
can be used but I'm assuming it can't be used here because
enemy1.getPosition().equals(player.getGun1Position())
gives an error when I try it.
NOTE: I cannot change the fields to public because this is for an assignment and the fields need to be private.
Any help would be appreciated :)
I'll briefly walk you through comparisons.
1) Primitives just need == operator to match values except, String values which are not permitives will compare their memory locations. for strings use .equals().
2) For objects of primitives like Integer,Double still compares the memory location with == operator. You need to invoke their .equals to compare them. If you have your own class you need to define your own version of equals method, means overriding.
Have you tried == yet?
If it is truly retiring a integer, than == is the way to go.
You can not call functions on primitives like int, char, double, float, long,short,byte. So there is no .equals() to call.
In the case of classes, you need to call .equals(), because a class variable is like a pointer, so you don't want to compare two pointers to each other with ==. However, primitive variables just contain their "values", so == is perfect for comparing values.
If you haven't tried this, you need to be more experimental with your coding.
Just test it.
System.out.println(enemy1.getPosition()+" == "+ player.getGun1Position()+": "+(enemy1.getPosition()==player.getGun1Position()));
if(enemy1.getPosition()==player.getGun1Position())
{
//blah
}
If that doesn't work, then you are not returning an int primitive, but instead an Integer object (note the capital I).
In this case,
if(enemy1.getPosition().equals(player.getGun1Position()))
OR
if(enemy1.getPosition().getIntValue()==player.getGun1Position().getIntValue()))
Should work fine.

The behaviour of equals() method in Java [duplicate]

This question already has answers here:
Weird Integer boxing in Java
(12 answers)
What is the difference between == and equals() in Java?
(26 answers)
Closed 9 years ago.
Consider the following Java code:
Object a = new Integer(2);
Object b = new Integer(2);
System.out.println(a.equals(b));
Object x = new Object();
Object y = new Object();
System.out.println(x.equals(y));
The first print statement prints true and the second false.
If this is an intentional behavior, how this helps programming in Java?
If this is not an intentional behavior, is this a defect in Java?
I'm going to answer your question with reservations, but you should know that you are hurting yourself if the intent of the question was to get you to learn and your solution was to ask StackOverflow. That aside...
This behavior is intentional.
The default equals() method on java.lang.Object compares memory addresses, which means that all objects are different from each other (only two references to the same object will return true).
java.lang.Integer overrides this to compare the value of the Integers, so two different Integers both representing the number two compare equal. If you used == instead, you would get false for both cases.
Standard practice in Java is to override the equals method to return true for objects which have the same logical value, even if they were created at different times (or even with different parameters). It's not very useful to have objects representing numbers if you don't have a way to ask, "do these two things represent the same value?".
Incidentally, and this is a tangent here, Java actually keeps a cache of Integer objects for small values. So sometimes you may get two Integer objects where even the == operator will return true, despite you getting them from two different sources. You can even get code that behaves differently for larger integers than it does for smaller, without having it look at the integral values!
This is intended behaviour.
Object.equals() considers the object identity (i.e. an object is only equal to itself), which is the only thing you can do for generic objects.
Integer overrides the method to depend on the integer value, since two Integer objects with the same value are logically equal. Many other classes also override equals() since it's a core mechanism of the standard API and a lot of functionaliy e.g. in the collections framework depends on it.
Why do are you puzzled by the behaviour anyway? Most people are only confused by the == operator not behaving like that (it works like Object.equals()).
The equals method in Java serves a specific purpose: it determines if the objects are logically equal, i.e. their content is the same, whatever that may mean in the context of each specific class. This is in contrast to the objects being the same: two different objects could be logically equivalent.
Going back to your example, a and b are different objects that represent the same logical entity - an integer value of 2. They model the same concept - an integer number, and integer numbers with the same value are identical to each other. a and b are, therefore, equal.
The x and y objects, on the other hand, do not represent the same logical entity (in fact, they do not represent anything). That's why they are neither the same nor are equivalent.
It is intentional, of course.
When comparing Integer objects, equals returns true if their values (in your case, 1) are equal.
Applied on different objects of type Object, it returns false.
x.equals(x)
would return true.
See also Object.equals() doc. By the way, consider using Integer.valueOf(2) rather than new Integer(2) as it reduces memory footprint.
One last funny thing Integer.valueOf(2)==Integer.valueOf(2) will return true but Integer.valueOf(2000)==Integer.valueOf(2000) will return false because in the first case you will receive twice the same instance of the Integer object (there is a cache behind) but not in the second case because the cache is only for values between -127 to 128

HashMap (Java) giving wrong results

I have created a hash map in which each entry corresponds to 3 values
Key object values ( which are two in number)
I have created a class ,whose object i create and store the results in a hash map
This is my code below in which i compare my incoming data with the previous values in the hash map.If the same data comes then i just increment the counter of that data. I have taken the print statements in the the for loop . though the two strings match but still my code never comes in the if loop for increment the counter.Why?
for(i=1;i<=hMap.size();i++)
{
String skey = Integer.toString(i);
if(hMap.get(skey).olddata==comingdata)
{
hMap.get(skey).counter= hMap.get(skey).counter+1;
}
}
You haven't given nearly enough information about the types involved, but, but I strongly suspect that this is the problem:
if(hMap.get(skey).olddata==comingdata)
That will be comparing references, rather than for equality, if olddata and comingdata are references of some kind. (EDIT: By the sounds of it, they're string references.)
My guess is that you want:
String skey = Integer.toString(i);
if(hMap.get(skey).olddata.equals(comingdata))
{
hMap.get(skey).counter= hMap.get(skey).counter+1;
}
Or rather more efficiently, avoiding pointless lookups:
WhateverType value = hMap.get(Integer.toString(i));
if (value.olddata.equals(comingdata))
{
value.counter++;
}
I'd also suggest that if you're always going to look up by an integer, why not use an Integer key instead of always converting the integer into a string?
Additionally, it's worth following Java naming conventions, and you should make your fields private if they're not already.
If none of this helps, please post more code. The chances of the problem being in HashMap rather than in your code are incredibly small.
It's not clear the type of olddata, but maybe you should compare the values using equals():
if (hMap.get(skey).olddata.equals(comingdata))
In Java, == is used for either comparing primitive data types for equality or comparing object types for identity. If you need to compare two object types for equality, then you must use the equals() method, which is defined for all objects since it's inherited from the Object class, being aware that you also must override equals() and hashCode() in your class, providing implementations meaningful for that class.
You don't compare objects with == in Java unless you're trying to see if they have the same reference value.
if (hMap.get(skey).olddata.equals(comingdata)) {
...
You also shouldn't be exposing olddata like that; it should be available via a getter; e.g. getOldData()
It should be
if(hMap.get(skey).olddata.equals(comingdata))
Do you actually mean comingdata.equals(hMap.get(skey).olddata)? Furthermore be aware that equals(Object) and hashCode() must be correclty implemented.

How do sets differentiate between objects?

How does a set differentiate between objects in both Java and C++? Or do sets not differentiate them at all?
Take these for example:
C++
std::set<A> aset;
A a(1, 2); // Assume A has only two elements, and this constructor sets them both
aset.insert(a);
A a2(1, 2); // This would initialise a `A' object to the same values as `a', but a different object
aset.count(a2); // Would this return 1 or 0?
Java
set<A> aset;
A a = new A(1, 2); // Assume A has only two elements, and this constructor sets them both
aset.add(a);
A a2 = new A(1, 2); // This would initialise a `A' object to the same values as `a', but a different object
aset.contains(a2); // Would this return true or false?
In C++ the set depends on operator<() being defined for the class A, or that you supply a comparison object providing strict weak ordering to the set.
For Java it depends on the equals, hashcode contract.
For the Java part,
The method in charge of determining whether two objects are equal is:
public boolean equals(Object other)
Not to be confused with
public int hashCode()
Whose contract states that two equals objects must return the same number, but two objects that returned the same number may be, but are not necessarily, equal.
The default implementation for the equals method is equality by memory address, therefor if class A did not override the equals method the contains method will return false.
To have the set.contains(a2) method return true you must override the equals and hashCode method to comply as so:
public boolean equals(Object other) {
return other instanceof A && ((A) other).elem1 = this.elem1 && ((A) other).elem2 = this.elem2;
}
public int hashCode() {
return elem1 * 31 + elem2;
}
The hashCode is required (assuming you're using a HashSet) for the set to identify where in the internal representation of the set the object may be (i.e. where to look for it).
Search for HashSet\HashMap to understand the internal representation if you're interested.
As for the C++ part, If I remember correctly it depends on the correct operator overloading, but my C++ is rusty at best.
EDIT: I noticed you specifically asked about sets so I'll elaborate a bit more on how that:
While the equals method is what determines equality between two objects, some preliminary steps in the set implementation used (e.g. HashSet or TreeSet) might relay on something extra:
For example, the HashSet uses the hashCode() function to find the internal location the item might be in, so if A did not override/correctly implement the hashCode() function, the set.contains(a2) may return true or false (for default implementation it's non deterministic - depends on memory location and the current capacity of the set).
For a TreeSet internal implementation to correctly find items within it either the items contained must be implement the Comparable interface properly or the TreeSet itself must be supplied with a Comparator instance implemented properly.
for C++, according to set::insert in C++ Reference
Because set containers do not allow for duplicate values, the
insertion operation checks for each
element inserted whether another
element exists already in the
container with the same value, if so,
the element is not inserted and -if
the function returns a value- an
iterator to it is returned
.
They check for the values, unlike Java, which only checks for the address instead.
In Java at least, comparison is done on a hash code, which by default is created from the location of the object in memory. So in the Java part of the question, aset.contains(a2); would return false, as a2 points to a different part of the memory to a.
I'm afraid I can't comment on how C++ works!
Java calls the object's equals method, which, if you haven't overridden it, is the same as calling Object.hashCode().

Categories

Resources