GenericUser01
GenericUser01

Reputation: 457

Searching for a specific object in an ArrayList Java

I am trying to find a specific object based on user input. The user is to enter a name and a gender and then the program is supposed to search an ArrayList and see if there is a name and gender that matches. The object in the ArrayList has 3 instance variables, but the program only searches for 2. How can I search for only a select few characteristics in an ArrayList?

In my program I have:

int nameListLength = nameList.size();
   .
   .
   .

boolean done = false;
while (!done) {
   System.out.println ("Please enter a name:");
   String searchName = input.nextLine();
   if (searchName.equals("DONE")) {
      done = true;
   } else {
      System.out.println ("Please enter a gender:");
      String searchGender = input.nextLine();
      // Search the ArrayList.
      for (int i = 0; i < nameListLength; i++) {
         // See if the gender is in the ArrayList
         if (searchGender.equals(nameList.get(i).getGender())) {
            // See if the name matches the gender in the ArrayList
            if (searchName.equals(nameList.get(i).getName())) {
               System.out.println ("Match found");
            }
         }
      }
   }
}

Where nameList is the name of the ArrayList, getName() is the name of the method that returns the name stored in the object, and getGender() is the name of the method that returns the gender stored in the object. I put in debug statements to determine that the ArrayList is stoing the information correctly, I'm just having problems figuring out how to search for what I am looking for. I know there is a contains(Object o) method, but I am not sure if I can implement that here since I only need to match 2 characteristics of the object even though the object contains 3 pieces of data.

Upvotes: 0

Views: 9570

Answers (5)

Palcente
Palcente

Reputation: 635

in your "Person" object @Override the equals method, then use contains() method from collection.

`@Override
public boolean equals(Object obj) {
    final Product other = (Product) obj;
    if (obj==null){
           return false;}
    else if(this.name.equals(other.name) && this.gender.equals(other.gender{
          return true;}
    else{
         return false;}
}`

Upvotes: 0

Zielu
Zielu

Reputation: 8552

Generally your code looks ok even if it is a bit untidy. You claim that it does not work, but I cannot see the obvious bug so I would double check the input list and the search terms (like case specificity for example).

Do not override the equal just to be able to use contains as it would imply that you always are going to compare your object just by those two properties.

You may consisder using the new Stream API which has few methods that does exactly what you are looking for:

List<Yourtype> found = list.stream().filter(u -> u.getName().equals(searchName) && u.getGender().equals(searchGender)).collect(Collectors.toList());

check if there is a matching element

boolean isMath = list.stream().anyMatch(u -> u.getName().equals(searchName) && u.getGender().equals(searchGender));

take first matching:

Yourtype match = list.stream().findFirst(u -> u.getName().equals(searchName) && u.getGender().equals(searchGender)).get();

Upvotes: 2

user949300
user949300

Reputation: 15729

Collection.contains() ultimately uses equals() and hashCode() of your Object (Name? - I'm calling it that in this post). It would work if you wrote Name.equals() and Name.hashCode() to only use the two fields, not all three. However, that is probably incorrect. At some other time the third field would be important. Unfortunately, in Java, you cannot "plug and play" different equals() methods. At least, not at all easily.

However, you can use a Comparator along with the utilities in Collections. For example, within your Name class, implement

public static final NAME_AND_GENDER_COMPARATOR = new Comparator<Name>() {
  // code goes here
}

Then, call (you might want to do this on a copy of nameList, as it will reorder it)

Collections.sort(nameList, Name.NAME_AND_GENDER_COMPARATOR);

Now, everything is sorted. Then call

Name searchFor = new Name(theName, theGender);  // make a mock Name to search for
int index = Collections.binarySearch(nameList, searchFor, Name.NAME_AND_GENDER_COMPARATOR);
if (index >= 0)
   // found it

Upvotes: 0

red13
red13

Reputation: 427

As far as I understood your question, you want to fetch the matching Object based on the input.

You already posted a viable solution. You only need to get the Object with nameList.get(i) where your System.out.println ("Match found") is.

You can also use for()-Loops to cycle through every item in the list, so you don't need to take the long way by using the lenght.

boolean done = false;
YourObject result;
while (!done) {
   System.out.println ("Please enter a name:");
   String searchName = input.nextLine();
   if (searchName.equals("DONE")) {
      done = true;
   } else {
      System.out.println ("Please enter a gender:");
      String searchGender = input.nextLine();
      // Search the ArrayList.
      for (YourObject item: nameList) {
         // See if the gender is in the ArrayList
         if (searchGender.equals(item.getGender())) {
            // See if the name matches the gender in the ArrayList
            if (searchName.equals(item.getName())) {
               result = item;
            }
         }
      }
   }
}

result would be your matching Object

Upvotes: 0

Rami Del Toro
Rami Del Toro

Reputation: 1150

To use the List.contains method,you will need to implement the equals() method on the object that contains the data, so it can determine if the object is truly equal to another object.

In your instance you will simply implement that 2 out of 3 pieces of data needs to be equal so then the equals() method can return true.

Upvotes: 0

Related Questions