I was wondering how the method indexOf of an ArrayList is implemented. In fact I have override the equals method like this:
public class CustomObject {
#Override
public boolean equals(Object o) {
if(o instanceof CityLoader)
return ((CityLoader)o).getName() == this.name;
else if (o instanceof String)
return this.name.equals((String)o);
return false;
}
}
I though this will avoid me to override also the indexOf method but it seems I am totally wrong.
When I try
ArrayList<CustomObject> customObjects = new ArrayList<CustomObject>
... insert customobject into the arraylist ...
customObjects.indexOf(new String("name"))
indexOf return false but it should return true. (I checked the element I am looking for exists)
Am I totally wrong?
equals should never return true when the compared objects are not of the same type (in your case CustomObject's equals should always return false when o is not an instance of CustomObject).
The implementation of indexOf happens to use String's equals instead of your CustomObject's equals when you pass a String to it, and String's equals returns false when you pass to it a object that is not a String.
In addition, don't use == in comparison of Strings.
You should pass an instance of CustomObject to indexOf :
customObjects.indexOf(new CustomObject("name"))
(or whatever the constructor of CustomObject looks like)
Your equals method should look like this :
public boolean equals(Object o) {
if(!(o instanceof CityLoader))
return false;
CityLoader other = (CityLoader)o;
return other.name.equals(this.name);
}
customObjects.indexOf(new String("name"))
This is what you are doing wrong. You are looking for an index of a String inside a CustomObject object list.
From the java docs :
/**
* 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 <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*
* #param o element to search for
* #return the index of the first occurrence of the specified element in
* this list, or -1 if this list does not contain the element
* #throws ClassCastException if the type of the specified element
* is incompatible with this list
* (optional)
* #throws NullPointerException if the specified element is null and this
* list does not permit null elements
* (optional)
*/
int indexOf(Object o);
Related
The following is the source code for Conlletion.contains(Object o) in ArrayList:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
/**
* 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 <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
I want to know why not type check first,for example:
public boolean contains(Object o) {
if(o.getClass() != elementData[0].getClass())
return false;
return indexOf(o) >= 0;
}
This is more efficient when o is a different type,isn't it?
(ps:Sorry, my English is not very good, I don't know if I speak clearly)
Since elementData is always allocated as an Object[], the expression elementData.getClass().getComponentType() is the same as Object.class, so if (o.getClass() != elementData.getClass().getComponentType()) would pretty such always be true, i.e. contains() would pretty such always return false.
Your suggestion wouldn't work, that's why it's not done that way.
Besides, even if you could, it still wouldn't work, because the values of a Collection object can be any subclass of the type specified for the collection.
E.g. an ArrayList<Number> can contain a mix of Integer, Long, Double, ... objects, so even if elementData.getClass().getComponentType() would have returned Number.class, it would still be a bad type check.
I am only guessing but I think it was an api design decision.
Since Java supports overwriting the equals method- it is up to the programmer to decide what it means for two objects to be equal. In theory, two objects of different types can be considered equal in a certain domain. It is true that checking for type equality is common when implementing equals, but it is not a mandatory. Since contains is a method for the most general case, no assumptions were made regarding the domain it would be called in.
Let this be a definition of a matrix:
private List<<List<Object>> lines;
public boolean equals(Object o){
if(this==o)
return true;
if((o==null) || (this.getClass()!=o.getClass()))
return false;
Matrix m = (Matrix) o;
return ????;
}
how can I compare all those lines and columns.
Can I just use
return this.lines.equals(o.getLines());
??
Thanks
More or less, though that exact code doesn't quite work.
From the List.equals javadoc:
Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).)
You can indeed use this method to determine equality, but you need to cast o first. This is a safe cast because you already checked the class (though you might consider using instanceof Matrix instead).
return this.lines.equals(((Matrix)o).getLines());
I have a lot of statements like the following
boolean isIdEqual = (retrievedEdition.getId() == null && edition.getId() == null) || (retrievedEdition.getId() !=null && edition.getId() != null && retrievedEdition.getId().equals(edition.getId()));
that is used for unit testing. and I'm checking for null for several data types, like long, int, Integer, String.
I want a single function that can check for two data types and shorten the above statement and refactor that code.
Couldn't Objects.equals(Object, Object) work out for you?
Objects.equals(retrievedEdition.getId(), edition.getId());
From the JavaDoc:
Returns true if the arguments are equal to each other and false otherwise. Consequently, if both arguments are null, true is returned and if exactly one argument is null, false is returned. Otherwise, equality is determined by using the equals method of the first argument.
The Objects class was introduced in Java 7 and if you are using an earlier version the implementation looks like this:
/**
* Returns {#code true} if the arguments are equal to each other
* and {#code false} otherwise.
* Consequently, if both arguments are {#code null}, {#code true}
* is returned and if exactly one argument is {#code null}, {#code
* false} is returned. Otherwise, equality is determined by using
* the {#link Object#equals equals} method of the first
* argument.
*
* #param a an object
* #param b an object to be compared with {#code a} for equality
* #return {#code true} if the arguments are equal to each other
* and {#code false} otherwise
* #see Object#equals(Object)
*/
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
You can simplify that code using a ternary expression :
boolean isIdEqual = retrievedEdition.getId() != null ? retrievedEdition.getId().equals(edition.getId()) : edition.getId() == null;
There are multiple things here..
I'm checking for null for several data types, like long, int, Integer, String. --> You can't check for null in case of primitives.
Next,
I want a single function that can check for two data types
Something like this might work..
boolean checkForNull(Object o1, Object o2){
{
//check here
}
public class Validator {
public static boolean checkEqualsOrNull(Object o1, Object o2) {
if (o1 == null && o2 == null) {
return false;
} else {
return o1.equals(o2);
}
}
}
And you can use it as follow in your code
boolean isIdEqual = Validator.checkEqualsOrNull(retrievedEdition.getId() ,
edition.getId());
This is a general purpose function that you can use for all your check.
I'm familiar with the ways I can get an element position in array, especially the ones showed here: Element position in array
But my problem is I can't figure out how to convert this code to fit my needs.
What I want to check is if a String has a match in an ArrayList and if so, what's the index of the String in the ArrayList.
The annoying part is I managed to verify the String is in the ArrayList (see first line of my code)
listPackages is the ArrayList
current_package is the String I want to find its position in listPackages.
Here's my code:
if (listPackages.contains(current_package)) {
int position = -1;
for(int j = 0; j < listPackages.size(); j++) {
if(listPackages[j] == current_package) {
position = j;
break;
}
}
}
Would appreciate any help!
Thanks!
Use indexOf:
int index = listPackages.indexOf(current_package);
Note that you shouldn't generally use == to compare strings - that will compare references, i.e. whether the two values are references to the same object, rather than to equal strings. Instead, you should call equals(). That's probably what was going wrong with your existing code, but obviously using indexOf is a lot simpler.
just use the call listPackages.indexOf(current_package);
ArrayList.contains(Object o) calls indexOf(Object o) internally in ArrayList:
/**
* Returns <tt>true</tt> if this list contains the specified element.
* More formally, returns <tt>true</tt> if and only if this list contains
* at least one element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>.
*
* #param o element whose presence in this list is to be tested
* #return <tt>true</tt> if this list contains the specified element
*/
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
Hope this will help you.change your code like this:
if (listPackages.contains(current_package)){
int position=listPackages.indexOf(current_package);
}
Also if you will make position variable as global you can access its value outside this block of code. :)
use the indexof method to get the position -
listPackages.indexOf(current_package)
http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html#indexOf(java.lang.Object)
When you call remove(object o) on an arraylist in java, how does it compare the objects to find the correct one to remove? does it use the pointer? or does it compare the objects using the interface Comparable?
ArrayList remove() relies on the objects implementation of the Equal method. If no implementation has been done then the object is removed by Object's implementation of Equals which indeed is the pointer comparison.
From the documentation on ArrayList -
More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists)
Object equal method documentation -
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
You should always consult the API for this kind of information.
ArrayList.remove(Object o): Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged. More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists).
Perhaps you were confusing this with e.g. TreeSet:
java.util.TreeSet: Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal.
(Unfortunately e.g. TreeSet.remove method itself doesn't have any explicit reminder of the above caveat, but at least it's prominently placed at the top of the class documentation)
An illustrative example
The following snippet illustrates the difference in behaviors between collections that use equals (such as an ArrayList) and collections that use compare/compareTo (such as a TreeSet).
import java.util.*;
public class CollectionEqualsCompareTo {
static void test(Collection<Object> col, Object o) {
col.clear();
col.add(o);
System.out.printf("%b %b %b %b%n",
col.contains(o),
col.remove(o),
col.contains(o),
col.isEmpty()
);
}
public static void main(String[] args) {
Object broken1 = new Comparable<Object>() {
// Contract violations!!! Only used for illustration!
#Override public boolean equals(Object o) { return true; }
#Override public int compareTo(Object other) { return -1; }
};
Object broken2 = new Comparable<Object>() {
// Contract violations!!! Only used for illustration!
#Override public boolean equals(Object o) { return false; }
#Override public int compareTo(Object other) { return 0; }
};
test(new ArrayList<Object>(), broken1); // true true false true
test(new TreeSet<Object>(), broken1); // false false false false
test(new ArrayList<Object>(), broken2); // false false false false
test(new TreeSet<Object>(), broken2); // true true false true
}
}
The docs answer your question:
Removes a single instance of the
specified element from this
collection, if it is present (optional
operation). More formally, removes an
element e such that (o==null ? e==null
: o.equals(e)), if the collection
contains one or more such elements.
It uses equals()
from the docs:
Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged. More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists). Returns true if this list contained the specified element (or equivalently, if this list changed as a result of the call).