Shaydoth
Shaydoth

Reputation: 112

Dealing with equality in an ArrayList in java

Say I have this section of code:

for(int i = 0; i < accounts.size(); i++) {
    if(UserID.equals(accounts.get(i).getUserID())) {
        if(accounts.contains(accounts.get(i))) {
            if(UserPass.equals(accounts.get(i).getPassword())) {
                System.out.println("True");
            }
        } else {
            typePhrase("unrecognised userID: '" + UserID + "'");
        }
    } else {
        typePhrase("unrecognised userID: '" + UserID + "'");
    }
}

It goes through an arrayList filled with objects, that have an ID and a password. I get two inputs from the user, one is the userID, and the other is the password. What I want is for it to go through every possible object that is saved in that arrayList, and if it finds a match, print true into the console, the issue that I'm having is that if you type in something wrong, it prints an message that it is unrecognised for every object in the arrayList. It also prints the message for every object that there is in the arrayList -1 if you type one in right. What do you suggest I do?

User class:

public class User {
    String userID;
    String password;

    public User(String ID, String Pass) {
        userID = ID;
        password = Pass;
    }

    public String getUserID() {
        return userID;
    }

    public String getPassword() {
        return password;
    }
}

EDIT:

ArrayList<User> accounts = new ArrayList<User>();

Upvotes: 1

Views: 407

Answers (6)

11thdimension
11thdimension

Reputation: 10633

You're struggling with whether to use contains() of List or to use a simple for loop. It can be done both ways, below is the code sample for both. For using the contains you'll have to add an equals() overridden method to User.

From the List.contains() documentation

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)).

With For Loop

import java.util.*;

public class TestMain {
    public static void main (String[] args) {
        List<User> accounts = new ArrayList<User>();
        User user1 = new User("test", "test");
        User user2 = new User("test1", "test1");

        accounts.add(user1);
        accounts.add(user2);

        String userId = "test";
        String userPass = "test1";

        boolean matchFound = false;

        for(User account : accounts) {
            if(userId.equals(account.getUserID()) && userPass.equals(account.getPassword())) {
                System.out.println("True");
                matchFound = true;
            }
        }

        if(!matchFound) {
            System.err.println("unrecognised userID: '" + userId + "'");
        }
    }
}

class User {
    String userID;
    String password;

    public User(String ID, String Pass) {
        userID = ID;
        password = Pass;
    }

    public String getUserID() {
        return userID;
    }

    public String getPassword() {
        return password;
    }
}

With contains() and equals()

import java.util.*;

public class TestMain2 {
    public static void main (String[] args) {
        List<User> accounts = new ArrayList<User>();
        User user1 = new User("test", "test");
        User user2 = new User("test1", "test1");

        accounts.add(user1);
        accounts.add(user2);

        String userId = "test1";
        String userPass = "test1";

        boolean matchFound = accounts.contains(new User(userId, userPass));

        if(!matchFound) {
            System.err.println("unrecognised userID: '" + userId + "'");
        } else {
            System.out.println("True");
        }
    }
}

class User {
    String userID;
    String password;

    public User(String ID, String Pass) {
        userID = ID;
        password = Pass;
    }

    public String getUserID() {
        return userID;
    }

    public String getPassword() {
        return password;
    }

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

        if(user != null && user instanceof User) {
            User userType = (User)user;
            boolean userIdMatched = (userID == null) ? userType.getUserID() == null : userID.equals(userType.getUserID());
            boolean passwordMatched = (password == null) ? userType.getPassword() == null : password.equals(userType.getPassword());

            isEqual =  userIdMatched && passwordMatched;
        }


        return isEqual;
    }
}

Upvotes: 0

Daniel Rodriguez
Daniel Rodriguez

Reputation: 617

Instead of printing true or not found, you can keep a boolean variable with whether you have found a match or not.

boolean found = false
for each value in the array
   if it's a match set found to true
   if it's not a match do nothing, i.e. continue to next position
if (found) print "true" else print "not found"

You can also break out of loop if you found a match, no need to keep checking for more matches.

boolean found = true
for each value in the array
   if it's a match set found to true and break out of loop
   if it's not a match do nothing, i.e. continue to next position
if (found) print "true" else print "not found"

Even better, you can move the code to a method that returns boolean and get rid of the variable.

boolean isThereAMatch() {
    for each value in the array
       if it's a match set return true
       if it's not a match do nothing, i.e. continue to next position
    return false
}

And you can call it to check what to print.

if (isThereAMatch()) print "true" else print "not found"

Upvotes: 0

Adrian Shum
Adrian Shum

Reputation: 40036

Not sure if implementing equals() is a wise choice here. However, isn't that what you are trying to do as simple as:

boolean found = false;
for (User u : accounts) {
  if (userId.equals(u.getUserId()) && userPass.equals(u.getPassword()) {
    found = true;
    break;
  }
}

You may even use stream API if you are in Java 8+

accounts.stream().anyMatch(u -> userId.equals(u.getUserId()) 
                              && userPass.equals(u.getPassword());

Upvotes: 0

ajb
ajb

Reputation: 31689

This is a mistake I see newer programmers often make. You're searching through a list to see if any element meets some condition (e.g. ID and password match). If no element meets the condition, you do something that indicates an error.

But you can't tell if there's an error until you've gone through every element of the list. Therefore, any error message has to occur after the loop is completely done, right? Not in the middle of the loop. But you've put your "unrecognised" message in the middle of the loop. That can't work.

There are several common idioms to solve this, but here's a simple one:

boolean found = false;
for (whatever-your-loop-should-look-like) {
     if (the-current-element-meets-the-condition) {
         found = true;
         break;
     }
}
if (!found) {
     whatever-action-you-take-when-it-isn't-found;
}

Upvotes: 1

OneCricketeer
OneCricketeer

Reputation: 191681

Remove this check... It makes no sense while you loop over those objects to check if the current object is inside the list of objects it came from.

if(accounts.contains(accounts.get(i))) {

Without this, your code prints True (but continues to check the rest of the list) when the userID and password match. Otherwise, the other message is printed. If you want to stop the loop when you print True, put break there.

To address the problem, though, User.equals() is not implemented, so the default way to compare objects is used (via the hashcode method).

You should implement that to compare equality of userID and password.

Upvotes: 0

Marcel Dias
Marcel Dias

Reputation: 4521

You should implement equals method in the User class:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    User user = (User) o;

    if (!getUserID().equals(user.getUserID())) return false;
    return getPassword().equals(user.getPassword());

}

Then you can create a new User with the typed information and just check if the list contains this User:

User user = new User("typedUserId", "typedPassword");
System.out.println(accounts.contains(user));

Upvotes: 5

Related Questions