简体   繁体   中英

Why does my program say the ArrayList element exists when I try to add it even though it's new?

I am adding elements to an ArrayList and I have it designed to show an error whenever the user tries to add a preexisting element (same for when it tries to remove a nonexistent element). From what it is showing, it adds the new element but still says that the element matches one that is already in the ArrayList. What have I been overlooking? The ArrayList is created and manipulated in the FacebookUser.java class. Thanks (and I apologize in advance if it's a silly mistake).

DriverClass.java

public class DriverClass {

    public static void main(String[] args) {

        FacebookUser fu0 = new FacebookUser("Samuel", "password1");
        FacebookUser fu1 = new FacebookUser("Michael", "password2");
        FacebookUser fu2 = new FacebookUser("Amy", "password3");
        FacebookUser fu3 = new FacebookUser("Eugene", "password4");
        fu0.setPasswordHint("p1");
        fu3.setPasswordHint("p4");

        fu0.friend(fu1);
        fu0.friend(fu2);
        fu0.friend(fu3);
        fu0.friend(fu3);

        System.out.println(fu0.getFriends());

        fu0.defriend(fu1);
        fu0.defriend(fu1);

        System.out.println(fu0.getFriends());

        fu0.getPasswordHelp();
        fu3.getPasswordHelp();
    }

}

FacebookUser.java

import java.util.ArrayList;

public class FacebookUser extends UserAccount {

    private String passwordHint;
    private ArrayList<FacebookUser> friends = new ArrayList<FacebookUser>();

    public FacebookUser(String username, String password) {
        super(username, password);
        friends = new ArrayList<FacebookUser>();
    }

    @Override
    public void getPasswordHelp() {
        System.out.println("Password Hint: " + passwordHint);

    }

    void setPasswordHint(String hint) {
        passwordHint = hint;
    }

    void friend(FacebookUser newFriend) {
        System.out.println(friends.size());
        if (friends.size() == 0) {
            friends.add(newFriend);
        } else {
            for (int i = 0; i < friends.size(); i++) {
                if (friends.get(i).equals(newFriend)) {
                    System.out.println("That person is already in your friends list.");
                    break;
                } else if (!friends.get(i).equals(newFriend) && i == friends.size() - 1) {
                    friends.add(newFriend);
                }
            }
        }
    }

    void defriend(FacebookUser formerFriend) {
        if (friends.size() == 0) {
            System.out.println("That person is not in your friends list.");
        } else {
            for (int i = 0; i < friends.size(); i++) {
                if (friends.get(i).equals(formerFriend)) {
                    friends.remove(i);
                    break;
                } else if (!friends.get(i).equals(formerFriend) && i == friends.size() - 1) {
                    System.out.println("That person is not in your friends list.");
                }

            }
        }

    }

    ArrayList<FacebookUser> getFriends() {
        ArrayList<FacebookUser> friendsCopy = new ArrayList<FacebookUser>();
        for (int i = 0; i < friends.size(); i++) {
            friendsCopy.add(friends.get(i));
        }
        return friendsCopy;
    }

}

UserAccount.java

public abstract class UserAccount {

    private String username;
    private String password;
    private boolean active; 

    public UserAccount(String username, String password) {
        this.username = username;
        this.password = password;
        active = true;
    }

    public boolean checkPassword(String password) {
        if (password.equals(this.password)) {
            return true;
        } else {
            return false;
        }
    }

    public void deactivateAccount() {
        active = false;
    }

    public String toString() {
        return username;
    }

    public boolean checkActive() {
        if (active == true) {
            return true;
        } else {
            return false;
        }
    }

    public abstract void getPasswordHelp();

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((username == null) ? 0 : username.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        UserAccount other = (UserAccount) obj;
        if (username == null) {
            if (other.username != null)
                return false;
        } else if (!username.equals(other.username))
            return false;
        return true;
    }

}

Execution:

0
1
That person is already in your friends list.
2
That person is already in your friends list.
3
That person is already in your friends list.
[Michael, Amy, Eugene]
That person is not in your friends list.
[Amy, Eugene]
Password Hint: p1
Password Hint: p4

Your loop is wrong:

for (int i = 0; i < friends.size(); i++) {
    if (friends.get(i).equals(newFriend)) {
        System.out.println("That person is already in your friends list.");
        break;
    } else if (!friends.get(i).equals(newFriend) && i == friends.size() - 1 ) {
        friends.add(newFriend);
    }
}

You are iterating through the friends list, then you add it when you get to the end, then the friends list becomes one larger, so then you compare with the one you just added, and it says it is already there.

You want this:

boolean alreadyThere = false;
for (int i = 0; i < friends.size(); i++) {
    if (friends.get(i).equals(newFriend)) {
         System.out.println("That person is already in your friends list.");
         alreadyThere = true;
         break;
    }
}

if(!alreadyThere) {
    friends.add(newFriend);
}

More simply, it could be this:

if(friends.contains(newFriend)) {
     System.out.println("That person is already in your friends list.");
} else {
     friends.add(newFriend);
}

You're comparing against size() in your for loop, even though you are also potentially adding items to the list in the loop, so you end up comparing the item against itself on the last iteration.

for (int i = 0; i < friends.size(); i++) { // result of size() will change
   if (friends.get(i).equals(newFriend)) {
      System.out.println("That person is already in your friends list.");
      break;
   } else if (!friends.get(i).equals(newFriend) && i == friends.size() - 1) {
      friends.add(newFriend);
   }
}

You can just extract the result of calling size() so that it doesn't change when you add a new item. Or you could also break from the loop after adding the item.

Save size:

int size = friends.size();
for (int i = 0; i < size; i++) {
   if (friends.get(i).equals(newFriend)) {
      System.out.println("That person is already in your friends list.");
      break;
   } else if (!friends.get(i).equals(newFriend) && i == friends.size() - 1) {
      friends.add(newFriend);
   }
}

Or, probably better, use break once you've decided that you should add the item:

for (int i = 0; i < friends.size(); i++) {
   if (friends.get(i).equals(newFriend)) {
      System.out.println("That person is already in your friends list.");
      break;
   } else if (!friends.get(i).equals(newFriend) && i == friends.size() - 1) {
      friends.add(newFriend);
      break;
   }
}

And then, an altogether better solution might be to avoid the loop and use contains instead:

void friend(FacebookUser newFriend) {
    System.out.println(friends.size());
    if (friends.contains(newFriend)) {
        System.out.println("That person is already in your friends list.");
        return;
    }

    friends.add(newFriend);
}

You are going in the right direction, but the iteration over the last added friend is the problem.

A quick fix could be breaking the loop after adding:

friends.add(newFriend);
break;

But it isn't a proper solution. We can use the contains in here:

if (friends.contains(newFriend)) {
    System.out.println("That person is already in your friends list.");
    return;
}
friends.add(newFriend);

When you add newFriend to the list, its size grows and so the loop execute one more time actually comparing newFriend to itself and so displaying the message.

The quick fix is to add a break; but this make things quite complex...

To me you could just write:

if (friends.contains(newFriend)) {
    System.out.println("That person is already in your friends list.");
} else {
    friends.add(newFriend)
}

without having to loop manually on the list elements.

But an even simpler solution would be to implement equals/hashCode for FacebookUser (required anyway for proper use of contains and finding the right friend) and use a Set of friends rather than a list. The Set structure always ensure there no duplicate and would perform much faster if there was to be many friends.

private Set<FacebookUser> friends = new HashSet<FacebookUser>();

[...]

if (!friends.add(newFriend)) {
   System.out.println("That person is already in your friends list.");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM