简体   繁体   English

在Java中处理ArrayList中的相等性

[英]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. 它通过一个充满对象的arrayList,该对象具有一个ID和一个密码。 I get two inputs from the user, one is the userID, and the other is the password. 我从用户那里得到了两个输入,一个是用户ID,另一个是密码。 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. 我想要的是让它遍历保存在该arrayList中的每个可能的对象,如果找到匹配项,则将true打印到控制台中,我遇到的问题是,如果您键入错误的内容,则会打印出来一条消息,表明无法对arrayList中的每个对象进行识别。 It also prints the message for every object that there is in the arrayList -1 if you type one in right. 如果在右边键入一个,它还会为arrayList -1中存在的每个对象输出消息。 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>();

You should implement equals method in the User class: 您应该在User类中实现equals方法:

@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));

This is a mistake I see newer programmers often make. 我看到这是新程序员经常犯的错误。 You're searching through a list to see if any element meets some condition (eg ID and password match). 您正在搜索列表以查看是否有任何元素符合某些条件(例如,ID和密码匹配)。 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;
}

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. 否则,当用户ID和密码匹配时,您的代码将输出True(但将继续检查列表的其余部分)。 Otherwise, the other message is printed. 否则,将打印其他信息。 If you want to stop the loop when you print True, put break there. 如果要在打印True时停止循环,请在此处放置break

To address the problem, though, User.equals() is not implemented, so the default way to compare objects is used (via the hashcode method). 但是,为了解决该问题,未实现User.equals() ,因此使用了比较对象的默认方式(通过hashcode方法)。

You should implement that to compare equality of userID and password. 您应该实现它以比较用户ID和密码的相等性。

Not sure if implementing equals() is a wise choice here. 不知道在这里实现equals()是否是明智的选择。 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+ 如果您使用Java 8+,甚至可以使用流API。

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

Instead of printing true or not found, you can keep a boolean variable with whether you have found a match or not. 可以使用布尔变量来确定是否找到匹配项,而不是打印true或not found。

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"

You're struggling with whether to use contains() of List or to use a simple for loop. 您正在努力使用List contains()还是使用简单的for循环。 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 . 为了使用contains,您必须向User添加一个equals()覆盖的方法。

From the List.contains() documentation List.contains()文档

Returns true if this list contains the specified element. 如果此列表包含指定的元素,则返回true。 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)). 更正式地讲,当且仅当此列表包含至少一个元素(e == null?e == null:o.equals(e))时,返回true。

With For Loop 与For循环

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() 与contains()和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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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