26

Assuming I have class like this:

class A {
  int elementA;
  int elementB
}

I also have an ArrayList like this: ArrayList<A> listObj.

How can I check if that list contains an object using only some of the properties of A? E.g. considering only elementA for finding if object newA{elementA} is already in the list?

For object A I have defined an equals method, where I consider only the elementA, however this is not enough.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Saulius S
  • 391
  • 2
  • 4
  • 12
  • 1
    Show your `equals` method. – AllTooSir Apr 29 '13 at 07:30
  • 1
    If you have overridden your equals() correctly, then listObj.contains(new A(elemAvalue)) should work. Note that you should also override hashCode only considering elementA value, though it's not functionally relevant for this example. – misberner Apr 29 '13 at 07:42
  • `if (!days.contains(getDate())) { days.add(getDate()); }` – Saulius S Apr 29 '13 at 07:47
  • 1
    for equals i use [here is example](http://javarevisited.blogspot.dk/2011/02/how-to-write-equals-method-in-java.html) as source (equals and hashCode) – Saulius S Apr 29 '13 at 08:12

7 Answers7

33

List#contains() method uses the equals() method to evaluate if two objects are the same. So, you need to override equals() in your Class A and also override the hashCode().

@Override
public boolean equals(Object object)
{
    boolean isEqual= false;

    if (object != null && object instanceof A)
    {
        isEqual = (this.elementA == ((A) object).elementA);
    }

    return isEqual;
}

@Override
public int hashCode() {
    return this.elementA;
}
AllTooSir
  • 48,828
  • 16
  • 130
  • 164
  • This works fine as long as you have to compare the A elements, but as soon as the requirement changes you can throw this out, not to mention that you might want to use the equals or hashcode methods other places, I would go with a Comparator thats for sure. – Peter Jaloveczki Apr 29 '13 at 08:07
  • 2
    Fair enough! But List `contains()` uses the `equals` method, not `Comparable.compareTo()` ! – AllTooSir Apr 29 '13 at 08:17
  • Thanks for the solution. For newbies like me: If `elementA` is `String` type, then use `isEqual = (this.elementA.equals(((A) object).elementA));` – Muhammad Saqib Aug 24 '16 at 15:39
  • 1
    In case "elementA" is a String, we need not override hashCode() method – Anubhav Apr 01 '20 at 13:20
4

You could adapt your equals to accomodate for your needs, but you could also use one of the powerful collection libraries that already exists, like commons-collections, Guava or lambdaj. They all have iteration and predicate constructs that allow you to "explore" your collections based on some predicate.

Example with Commons Collections:

boolean contains = CollectionUtils.exists(myArrayList, new Predicate<A>() {
    public boolean evaluate(A theA) {
        // Do the comparison
    }
});
NilsH
  • 13,705
  • 4
  • 41
  • 59
1

I wouldn't override equals for this. Even though {1, 1} and {1, 2} cannot both occur in your list, the two objects are not equal.

I would use a Map instead:

Map<Integer, A> map = new HashMap<>();
A a1 = new A(1, 1);
A a2 = new A(1, 2);

map.put(a1.elementA, a1);

// test if key is contained
boolean contains = map.containsKey(a2.elementA);

// overwrite a1 with a2
map.put(a2.elementA, a2);
Vincent van der Weele
  • 12,927
  • 1
  • 33
  • 61
0

The hashCode() and equals() of arrays are a bit broken when it comes to this (it is a long different discussion why).

A possible work around is to use ArrayList<ArrayList<String>> instead of ArrayList<String[]>, the equals() method for ArrayList will be as you expect it to.

For example:

   ArrayList<String> l1 = new ArrayList<>();
    ArrayList<String> l2 = new ArrayList<>();
    l1.add("asdf");
    l2.add("asdf");
    ArrayList<ArrayList<String>> coll = new ArrayList<>();
    coll.add(l1);
    System.out.println(coll.contains(l2));

Will yield true, as expected

Also refer below link

Most efficient way to see if an ArrayList contains an object in Java

Community
  • 1
  • 1
Hariharan
  • 3,191
  • 4
  • 19
  • 31
0

All the above solution will suits your question. What i like to suggest you here is !!! When ever you use collection, always have your variable datatype to its super class. which will help you to make more manipulation and convert to any of its sub-class.

Ex:
List<String> myList = new ArrayList<String>();

The advantage that the implementation of the List can change (to a LinkedList for example), without affecting the rest of the code. This is will be difficult to do with an ArrayList, not only because you will need to change ArrayList to LinkedList everywhere, but also because you may have used ArrayList specific methods.

0

For comparing the object value in arrayList. Follow this Link. How to compare Objects attributes in an ArrayList?

I hope this solution will help you. Thanks

alessandrio
  • 4,282
  • 2
  • 29
  • 40
Aman Goyal
  • 409
  • 5
  • 8
0
List<Upload> mUploadPost = new ArrayList<Upload>();
Upload upload = new Upload();
upload.addName("Mpendulo");
upload.addLastName("Mtshali");
if(!mUploadPost.contains(upload)){
    mUploadPost.add(upload);
}