Java, Integers not unique but how are they compared in collections? - java

I used this straight-forward method:
Collection<Integer> aCollection = Arrays.asList(1,2,3,4,5,6);
Integer a = new Integer(5);
if( aCollection.contains(a) )
System.out.println("aCollection contains 5");
Result is "aCollection contains 5". Integers are not unique objects in whole system, but in this case are the "5" in Collection<Integer> and the new Integer(5) in fact references to the same object?
Can I safely assume that any collection will behave this way when calling .contains()?
I am not sure because when comparing references and values by == result is:
3 == new Integer(3)
new Integer(3) != new Integer(3)
new Integer(3) == 3

contains does not compare by reference. new Integer(50000) is different from another call to new Integer(50000). However, firstInt.equals(new Integer(50000)) will return true, hence contains will work. I use higher numbers since interning can happen with lower ones.
0-127 will be put into a fixed pool when performing boxing but not when explicitly creating new objects so you'll have the same reference to the same value, but above that, you have no guarantee of any interning, and references may be to different Integer objects for the same value. Integer.valueOf( will attempt to intern where appropriate, namely always within [-128, 128) and with no specification for or against interning outside this range.
Can I safely assume that any collection will behave this way when calling .contains()?
You can assume that .contains(Object o) will return true if and only if one or more members of the collection satisfies thatmember.equals(o), or if o is null, and there is at least one null member.
Technically:
Returns true if this collection contains the specified element. More
formally, returns true if and only if this collection contains at
least one element e such that (o==null ? e==null : o.equals(e)).

It is defined in JavaDoc:
boolean contains(Object o)
Returns true if this collection contains the specified element. More
formally, returns true if and only if this collection contains at
least one element e such that (o==null ? e==null : o.equals(e)).
In words: If o is null, contains will return true if the collection contains a null element, otherwise it will return true if and only if there is an element that equals() the one you are searching for.
Every call to new Integer(5) will return a different reference, but all the objects are equal to one another according to the equals() method of the Integer class:
Compares this object to the specified object. The result is true if
and only if the argument is not null and is an Integer object that
contains the same int value as this object.

.contains() of an collection calls the .equals() method internally.
In your case you are using an Integer object. And an Integer object .equals() might return true in all the cases you have listed.
However that might not be case for a custom object you have say Person.
Now for a collection
Collection<Person> aCollection = Arrays.asList(b,c,d);
Person a = new Person("Abhishek");
may return false. because you have not overridden the .equals() method in your Person class

Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.
http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

Related

How to force eclipse to create different object references

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)

Java Arraylist.contains(Object) always returns false [duplicate]

This question already has answers here:
Java ArrayList Contain always return false although it contain the same value
(4 answers)
Closed 7 years ago.
Basically i want to create a class "Screws". This class shall describe a Screw by Type, length, thickness etc. I also want to create a "storage" class, that stores said "Screws" in all variances. The type, length etc. is limited to 7 and 3 (so there will be a limited amount of possibilities)
public class Screws{
public Screws(int typ,double durchmesser,double laenge,double gangHoehe){
this.schraubenArt = typ;
this.durchmesser=durchmesser;
this.laenge=laenge;
this.gangHoehe=gangHoehe;
}
}
Now i want to create a storage "unit", that will be an arraylist. I want to fill it with objects of "Screws". Afterwards i want to be able to check if a certain Scredobject is contained in the list.
import java.util.ArrayList;
public class Lager {
private Screws schrauben;
private ArrayList<Screws>Kreuzschlitzlager;
public Lager(){
Kreuzschlitzlager = new ArrayList<>();
for(int durchmesser=0; durchmesser <=3; durchmesser++){
for(int laenge=0; laenge <= 3; laenge++){
for(int ganghoehe=0; ganghoehe <=3; ganghoehe++){
Kreuzschlitzlager.add(new Screws (1,durchmesser,laenge,ganghoehe););
}}}}
public boolean checkForObject(Screws object){
return Kreuzschlitzlager.contains(object);
}
Now my problem is, i get a long list of objects i can "get" the properties of, but if i checkForObject(Anything) it will always give me a "false". I can't figure out why though. Don't worry about the class Screws, it's not nearly done. :D
So, how do i check if an array list contains a certain object, why is it not working in this case and can i get the index of the object with .IndexOf?
You're right; the Screws class isn't done. The ArrayList class calls the equals method to determine if the element is equal to the argument to contains, but you don't override equals. Your Screws class is inheriting equals from Object, and it will only return true if it's the same exact object.
Override the equals method, signature boolean equals(Object obj) in Screws. You will need to code the logic for determining equality yourself.
Additionally, the contract for equals means that it needs to be consistent with hashCode. For this small application, it's not necessary, but generally you should also override hashCode to be consistent with equals.
Take a look at the javadoc for List.contains
boolean contains(Object o)
Returns true if this list contains the specified element. More
formally, returns true if and only if this list contains at least one
element e such that (o==null ? e==null : o.equals(e)).
Specified by:
contains in interface Collection
Parameters:
o - element whose presence in this list is to be tested Returns:
true if this list contains the specified element
Throws:
ClassCastException - if the type of the specified element is incompatible with this list (optional)
NullPointerException - if the specified element is null and this list does not permit null elements (optional)
If you don't specify an equals method for your class Screws, it's going to check if they are the same object. Define an equals method.
in your Screws class, you need to override the method equals(...) and implement how two Screws should be equal
contains method of ArrayList does this:
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e))
For example, we initialize two Screws objects which contains the exact values.
Screws screws1 = new Screws(1, 1.0, 1.0, 1.0, 1.0);
Screws screws2 = new Screws(1, 1.0, 1.0, 1.0, 1.0);
Kreuzschlitzlager.add(screws1);
Kreuzschlitzlager.contains(screws2); // this returns false
It only compares the memory address by default. screws1 and screws2 have different memory addresses, so they are not the same object, and they are not equal. You have to override boolean equals(Object) and int hashcode() in your Screws class, define your own way how two Screws objects are equal

Finding index value of an Object arrayList using indexOf() in Java

This method scans the current staff Employee array to see whether
there is a match between the any member of staff and the Employee
passed in.
Return -1 if there is no match, and the index number of the Employee
if there is a match.
Now my question is that, how can I use -
indexOf();
method properly to get the index value of the object and in turn the employee whose empId matches with the employee passed in
public int findEmployee(Employee emp) {
int index = -1;
for (Employee s : staff) {
if (emp.getEmpId() == s.getEmpId()) {
index = indexOf(); //how to use this
}
}
return index;
}
I'm open to any other ways of comparing as I know indexOf() can search and find the empId for me. So if I have to do away with the if statement all together I don't mind. I think it will make the code more effective.
Going from comments because an explanation of indexOf() would likely be too long for comments. Other answerers provide good alternatives, but I'll answer the way that is requested.
I'm assuming you're working with a List of some kind (e.g. staff is an ArrayList<Employee>), as the Arrays utility class doesn't appear to have an indexOf() method.
Unfortunately, I have no C++ experience, so I'm not sure what concepts in Java map over to C++ well. If you have any questions, feel free to ask.
The javadoc for ArrayList#indexOf(Object o) states:
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
The interesting portion is this:
returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i)))
So essentially, what indexOf() will do is loop over the list, until it finds an element such that:
if o == null, the element is also null
if o != null, o.equals(element) returns true
Or if no such element exists, then -1 will be returned. I assume the employee you're passing in is non-null, I'll focus on the second option there.
o.equals(element) is pretty self-explanatory. However, there is something to be careful for: If the Employee class does not override equals(), you'll likely not get the behavior you want. This is because the default implementation of equals() checks for reference equality (where the two references you're comparing point to the same underlying object, similar to what I'm guessing in C++ is two pointers pointing to the same location/object), not object equality (the "normal" equals, where two objects are equal if they "represent the same thing", even if they are distinct objects).
So it looks like in your case, if you want to match Employees by ID number, you'll need to write an equals() method that takes in an Object, checks to see if it's an Employee, and if it is, if the passed object's employee ID matches that of the employee you're calling equals() on. Of course, if such an equals() method already exists, then you don't have to do anything. If equals() is already overridden and has some different behavior, then you might be out of luck...
Also, be careful that the method signature you use is equals(Object o), and not equals(Employee e). Those are two different method signatures, and only the first will override Object#equals().
Once you have a proper equals() method written, indexOf() should do the rest of the work for you.
If each Employee has its own unique id, then you need to implement equals() method inside Employee object and return true if ids are equal, eg:
#Override
public boolean equals(Object object) {
return (object instanceof Employee) && (id != null)
? id.equals(((Employee) object).id) //change ".equals" to "=" if you use int instead of Integer, which I believe you apparently do.
: (object == this);
}

contains() compares by value, not reference?

I was surprised to see that equals() is apparently overridden for ArrayList<String>. Because contains() in Collection<> apparently compares values, not references. Of course, for Collection<Object>, references would be compared. In the program below, shouldn't I get false on the second line?
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("Obama");
al.add("Reagan");
al.add("Bush");
al.add("Nyquist");
StringBuffer sb = new StringBuffer();
sb.append("Bush");
System.out.println("compares values? using constants " + al.contains("Bush"));
System.out.println("compares values? using local variable " + al.contains(sb.toString()));
}
run:
compares values? using constants true
compares values? using local variable true
Javdaocs for List are you friend. List.contains() relies on .equals():
boolean contains(Object o)
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).
String.equals() compares the Strings contents (characters):
public boolean equals(Object anObject) Compares this string to the
specified object. The result is true if and only if the argument is
not null and is a String object that represents the same sequence of
characters as this object.
This is exactly the output you should expect, and Collection<Object> would be no different. All Collection types, unless specified otherwise, use .equals(Object), and differing implementations violate the Collection contract. (And to be clear, upcasting a String to an Object does not change the behavior of its equals method.)
There is some precedent -- see e.g. the TreeSet implementations, which use comparison-based equality, and IdentityHashSet, which uses reference equality -- but these should usually be used only when the two notions of equality match, or for significant and unusual need.
you can try System.out.println(sb.toString().equals("Bush")); in your class and see what it returns. It will return true. So in the second case it is returning/printing true.

What is the difference between identity and equality in OOP?

What is the difference between identity and equality in OOP (Object Oriented Programming)?
identity: a variable holds the
same instance as another variable.
equality: two distinct objects can
be used interchangeably. they often
have the same id.
Identity
For example:
Integer a = new Integer(1);
Integer b = a;
a is identical to b.
In Java, identity is tested with ==. For example, if( a == b ).
Equality
Integer c = new Integer(1);
Integer d = new Integer(1);
c is equal but not identical to d.
Of course, two identical variables are always equal.
In Java, equality is defined by the equals method. Keep in mind, if you implement equals you must also implement hashCode.
Identity determines whether two objects share the same memory address. Equality determines if two object contain the same state.
If two object are identical then they are also equal but just because two objects are equal dies not mean that they share the same memory address.
There is a special case for Strings but that is off topic and you'll need to ask someone else about how that works exactly ;-)
Identity means it is the same object instance while equality means the objects you compare are to different instances of an object but happen to contain the same data.
Illustration (in java)
Date a = new Date(123);
Date b = new Date(123);
System.out.println(a==b); //false
System.out.println(a.equals(b)); //true
So a and b are different instances (different allocations in memory) but on the "data" level they are equal.
For instance,
In StackOverFlow:
identity: I am Michael, you are
sevugarajan, so we are not same.
equality: if we have same reputation
scores, we are equal in some ways.
In Java and similar languages which 'leak' the abstraction of a reference of an object, you can test whether two references refer to the same object. If they refer to the same object, then the references are identical. In Java, this is the == operator.
There is also an equals method which is used to test whether two objects have the same value, for example when used as keys of a HashSet (the hash code of equal objects should also be equal). Equal objects should have the same 'value' and semantics when used by client code.
Purer object-oriented languages do not have an identity comparison, as client code generally shouldn't care whether or not two objects have the same memory address. If objects represent the same real-world entity, then that is better modelled using some ID or key value rather than identity, which then becomes part of the equals contract. Not relying on the memory address of the object to represent real-world identity simplifies caching and distributed behaviour, and suppressing == would remove a host of bugs in string comparison or some uses of boxing of primitives in Java.
Think about the words "identical" and "equivalent". If two things are identical, they have the same identity; they are same thing. If they are equivalent, one can be substituted for the other without affecting the outcome; they have the same behavior and properties.
Identity: Two references to the same object (o1 == o2).
Equality: The method o1.equals( o2 ) returns true. This doesn't necessarily mean that the two objects contain (all) the same data.
In theory it's possible to override a method equals() to return false even for identical objects. But this would break the specification of Object.equals():
The equals method implements an equivalence relation on non-null object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
Identity concept is quite philosophical, that's why you shouldn't reconduce it just to references.
You can say that two identities are the same if a change to the first is reflected on the second and vice-versa. Of course this includes also sharing the same memory address but in general while identity is related to the attributes of the object, equality is used to check whenever two objects are identical, but this doesn't include identity.
The viceversa is quite obvious, if two items have the same identity they are also equal (in equality terms of being interchangeable).
For primitive types ( int , boolean , char, long , float ... )
== and != is equality test
and for Objects
== and != is identity test. [ it compares only the reference ]
equals method is used for equality test of Objects [ it can be overridden to compare specific attributes]
i found an excellent article on this
http://www.cs.cornell.edu/courses/cs211/2006sp/Lectures/L14-Comparison/L14cs211sp06.pdf
http://ocw.mit.edu/NR/rdonlyres/Electrical-Engineering-and-Computer-Science/6-170Fall-2005/D659DC53-FB1D-403C-8E35-2CAECBED266E/0/lec12.pdf
Quote
I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals. :D
Sir Winston Churchill
x == y is true only if there's the same object referenced by variables x and y.
x.equals(y) depends on the implementation of x.equals(), and is usually less strict that the above, as it compares the content of the object. (In Java, if x.equals(y), it must also be true that x.hashCode() == y.hashCode();)
Example:
Integer w = new Integer(3);
Integer x = new Integer(1);
Integer y = x;
Integer z = new Integer(1);
// all of these evaluate to true
y.equals(x) // it's the same object, of course the content is same
x.equals(z) // different objects, same content (`1`)
z.equals(y)
!w.equals(x); // the content is different (`3` vs `1`)
!w.equals(y);
!w.equals(z);
x == y // same object
z != x // different objects
y != z
w != x
Identical vs. Equal objects
Two objects are said to have identical states (deep equality) if the graphs representing their states are identical in every respect, including the OIDs at every level.
Two objects are said to have equal states (shallow equality) if the graphs representing their states are same, including all the corresponding atomic values. However, some corresponding internal nodes in the two graphs may have objects with different OIDs.
Example: This example illustrates the difference between the two definitions for comparing object
states for equality.
o2 = (i 2 , tuple, <a 1 :i 5 , a 2 :i 6 >)
o3 = (i 3 , tuple, <a 1 :i 4 , a 2 :i 6 >)
o4 = (i 4 , atom, 10)
o5 = (i 5 , atom, 10)
o6 = (i 6 , atom, 20)
In this example, the objects o1 and o2 have equal states (shallow equality), since their states at the atomic level are the same but the values are reached through distinct objects o 4 and o 5 .
However, the objects o1 and o3 have identical states (deep equality), even though the objects themselves are not because they have distinct OIDs. Similarly, although the states of o4 and o5 are identical, the actual objects o4 and o5 are equal but not identical, because they have distinct OIDs.
To add, identity is also known as referential check (references to objects, get it?) and equality as structural check by some authors. At the end of the day an object in memory abstract is just a map/table structure indexed at certain memory address. There can be one or many references (memory addresses) pointing to it. They all are referential-ly identical. When contents of same object is copied to another counterpart then both are structurally equal.

Categories

Resources