2

I'm trying to use a method to check if an arraylist contains an object with an attribute.

public class Network {
    // this variable is instantiated and set by the constructor
    private ArrayList<Person> persons;

    /**
     * Constructor for objects of class Network
     */
    public Network() {
        // initialize instance variables
        persons = new ArrayList<>();
        persons.add(new Person("name1"));
        persons.add(new Person("name2"));
    }

This is what i have at the moment, but i cant get it to work.

public Person lookupPerson(String personName) {
    boolean personContain = persons.contains(new Person(personName));

    if (personContain == true) {
        System.out.println("ye");
    } else {
        System.out.println("nah");
    }

    return null;
}
Zabuzard
  • 25,064
  • 8
  • 58
  • 82
Awaythrows8
  • 21
  • 1
  • 1
  • 5
  • `new Person()` creates a new object and therefore is totally unrelated to all existing objects in the list and thats why its not working – XtremeBaumer Sep 27 '17 at 09:57
  • Actually this is not good approach. You should use `LinkedHashMap` instead. – Oleg Cherednik Sep 27 '17 at 10:06
  • @oleg.cherednik if `Person.name` is unique, the `Map` won't work in that case. You will need to put a `List` into the value map. – AxelH Sep 27 '17 at 10:37

4 Answers4

6

Read ArrayList.contains doc.

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 will use the parameter equals method, is it defined in Person ? Probably not so it will use Object.equals that will check the references, not instance content.

Create the method like

class Person {
     ...
     @Override
     public boolean equals(Object o){
         if(o instanceof Person){
              Person p = (Person) o;
              return this.name.equals(p.getName());
         } else
              return false;
     }
}
AxelH
  • 14,325
  • 2
  • 25
  • 55
  • So Person equals method should be implemented. And if it is implemented so that 2 persons are equal if they have the same name, then the code of OP would work. – Naxos84 Sep 27 '17 at 10:19
  • 1
    Indeed. Also note that whenever implementing `equals` one should also implement the method `hashcode` with the *same logic*. There are many questions at SO for this type of problem, like seen here: [What issues should be considered when overriding equals and hashCode in Java?](https://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java) – Zabuzard Sep 27 '17 at 10:22
  • @Zabuza that's a good practice, but not necessary in this case (and I didn't want to add some complexity to this question). Nothing in the list will use the `hashcode`, but good point ! – AxelH Sep 27 '17 at 10:28
  • @AxelH I'm sorry. obviously I didn't pay enough attention when reading your answer. You already implemented an equals method in Person class that checks wether only names are equal ;) – Naxos84 Sep 27 '17 at 10:33
5

The problem

The reason why your approach did not work is because the List#contains (documentation) method uses the result of Person#equals to decide if an element from the list is the same as the argument. If you have not implemented this method than it searches the method in the inheritance tree of Person. As every object inherits from the class Object you will fall back to Object#equals (documentation) if no class on the way to Object has implemented equals. However this Object#equals method compairs objects by their identity (place in the memory). That means that if you create an object that has the same properties (like name and so on) it just will be a copy but not the same as the one in the list, per identity.

Note that there are many questions here at StackOverflow for this topic. If you're not familiar with it you should check it out. Here is an example explaining it in more detail: What issues should be considered when overriding equals and hashCode in Java?

There are multiple ways of solving this problem. Let's first consider a very straightforward and easy way.

Iterating manually

We manually iterate the list and check every entry regarding the relevant parameters.

public Person lookupPerson(String personName) {
    for (final Person person : persons) {
        // Access properties of person, usage of getter methods would be good
        if (person.name.equals(personName)) {
            // Found matching person
            return person;
        }
    }

    // Traversed whole list but did not find a matching person
    return null;
}

(like seen in the answer of @DeepakS)

Implement equals and hashCode, use indexOf

Now we let the list do the iterating and matching part by using List#indexOf (documentation). This approach is similar to yours with contains (documentation) but we would also like to get the element, not just check if its there or not.

public class Person {
    ...

    @Override
    public boolean equals(final Object o) {
        if (o == null) {
            return false;
        }
        if (!(o instanceof Person)) {
            return false;
        }
        if (o == this) {
            return true;
        }

        final Person other = (Person) o;
        return other.name.equals(this.name);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;

        result = prime * result;
        if (this.name != null) {
            result += this.name.hashCode();
        }

        return result;
    }
}

And the lookup method:

public Person lookupPerson(String personName) {
    // The needle to search for
    final Person needle = new Person(personName);

    // The needle will now be equals to list objects
    // regarding its equals method which only checks
    // for the name

    final int index = persons.indexOf(needle);
    if (index != -1) {
        // Get the element at this position
        return persons.get(index);
    } else {
        return null;
    }
}

(like seen in the answer of @AxelH)

Compact Java 8 solution

If you have Java 8 you may prefer a very compact variant. Therefore we use Stream#filter (documentation) which filters elements of a stream based on if the method returns true or false (a so called Predicate (documentation)). So we just need to implement a check for the name there and are finished.

public Person lookupPerson(String personName) {
    return list.stream()
        .filter(p -> p.name.equals(personName))
        .findAny();
}

(like seen in the answer of @GaneshToni)

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
  • I started writing the answer before some of the other answers came. But note that even reusing is allowed, if credits are given. I'll edit the answer. – Zabuzard Sep 27 '17 at 10:51
  • You may read [Summing up answers in the top answer](https://meta.stackoverflow.com/questions/319644/summing-up-answers-in-the-top-answer) or similar Meta questions. – Zabuzard Sep 27 '17 at 10:56
  • Read the [second answer](https://meta.stackoverflow.com/a/319703/4391450) in that meta. You will see the ethical problem of your answer.. I didn't downvote yours since you still have the java 8 answer that is fresh, but I could.. – AxelH Sep 27 '17 at 11:03
  • Feel free to give your vote as you like. As said, I did not intentionally create this answer to sum up others, I started writing as there where *zero* answers here. I see the problem but please do not put an ill intent on me. I could now delete the answer but in my opinion it has too much new content (clear problem description, many doc links, ...) and also improves other answers (complete hashCode & equals, Java 8 solution). If you feel unjustly treated you also have the option to flag the answer as *plagiarism* and a mod will decide, fair enough. – Zabuzard Sep 27 '17 at 11:22
0

If you are using Java 8 then use predicate. in predicte you can filter arraylist with given criteria and then check if the resultant arraylist size is zero or not. thus you can find object with prooerty is there or not.

0

if the below line is adding a person object with name "name1" attribute

 persons.add(new Person("name1")); 

then you can use @codematrix suggestion if you are using java 8 or u can use it like this instead of this line

boolean personContain = persons.contains((personName));

you can use

public Person lookupPerson(String personName) {
 boolean personContain =false;
 for(person per : persons){
  if(per.getName().equals(personName)){
    //you can return person Object as below
    //return per;
    personContain =true;
  }
 }
Deepak S
  • 9
  • 6