Java 迭代hashmap并创建唯一对象-尝试防止重复

Java 迭代hashmap并创建唯一对象-尝试防止重复,java,hashmap,Java,Hashmap,我在方法的上述部分的注释中解释了我试图做的事情: public int addPatron(String name) throws PatronException { int i = 0; //1. Iterate through a hashmap, and confirm the new name I am trying to add to the record doesn't already exist in the hashmap for (Map.Ent

我在方法的上述部分的注释中解释了我试图做的事情:

public int addPatron(String name) throws PatronException {
    int i = 0;
    //1. Iterate through a hashmap, and confirm the new name I am trying to add to the     record doesn't already exist in the hashmap
    for (Map.Entry<Integer, Patron> entry : patrons.entrySet()) {
        Patron nameTest = entry.getValue();
        //2. If the name I am trying to add already exists, we want to throw an exception saying as much.
        if (nameTest.getName() == name) {
            throw new PatronException ("This patron already exists");
            //3. If the name is unique, we want to get the largest key value (customer number) already in the hash, an increment by one.
        } else if (nameTest.getName() != name) {
            Map.Entry<Integer,Patron> maxEntry = null;
            for(Map.Entry<Integer, Patron> entryCheck : patrons.entrySet()) {
                if (maxEntry == null || entryCheck.getKey() > maxEntry.getKey()) {
                    maxEntry = entryCheck;
                    i = maxEntry.getKey();
                    i++;
                }
            }

        } else {
            throw new PatronException("Something's not working!");
        }
        //4. If everything is ok up to this point, we want to us the name and the new customer id number, and use those to create a new Patron object, which then gets added to a hashmap for this class which contains all the patrons.
        Patron newPatron = new Patron(name, i);
        patrons.put(i, newPatron);
    }
    return i;
}
测试失败,告诉我addPatron方法可以使用相同的名称两次

@乔恩·斯凯特:

我的赞助人类如下所示:

public class Patron {

//attributes
private String name = null;
private int cardNumber = 0;

//operations
public Patron (String name, int cardNumber){
    this.name = name;
    this.cardNumber = cardNumber;
}

public String getName(){
    return name;

}

public int getCardNumber(){
    return cardNumber;
}
public int addPatron(String name) throws PatronException {
    int maxKey = -1;

    for (Map.Entry<Integer, Patron> entry : patrons.entrySet()) {
        if (entry.getValue().getName().equals(name)) {
            // TODO: Consider using IllegalArgumentException
            throw new PatronException("This patron already exists");
        }
        maxKey = Math.max(maxKey, entry.getKey());
    }
    int newKey = maxKey + 1;
    Patron newPatron = new Patron(name, newKey);
    patrons.put(newKey, newPatron);
    return newKey;
}

}

您需要使用equals来比较java中的字符串对象,而不是==。因此,请替换:

if (nameTest.getName() == name) {
与:


问题的原因是如何使用比较运算符
==

当对两个对象使用此运算符时,测试的是指向同一对象的变量

要测试两个对象的值是否相等,应使用
equals()
方法或
compareTo
(如果可用)

对于String类,调用
equals
就足以检查存储的字符是否相同

比较对象的值 问题是如何比较名称。

尝试使用

nameTest.getName().equals(name)
而不是

nameTest.getName() == name
因为现在比较的是引用,而不是字符串的值。

再次查看您的代码


我又看了一遍你的代码,问题是,你的HashMap在测试开始时是空的。因此循环永远不会运行==>永远不会添加用户或抛出异常。

正如其他人所说,使用
==
比较字符串几乎肯定是不合适的。然而,它实际上不应该在您的测试用例中引起问题,因为您两次使用相同的常量字符串,所以
==
应该可以工作。当然,您仍然应该修复代码以使用
equals

还不清楚
Patron
构造函数或
getName
方法做了什么-这两种方法中的任何一种都可能导致问题(例如,如果它们创建字符串的新副本-这将导致测试失败,但通常也不必要)

更让我担心的是这句话:

// 3. If the name is unique, we want to get the largest key value (customer number) 
// already in the hash, an increment by one.
此注释位于主循环中。因此,到那时,我们不知道名称是唯一的-我们只知道它与此迭代中用户的名称不匹配

更令人担忧的是——我刚刚注意到了这一点——您也在迭代块中执行add。在我看来,你应该有更像这样的东西:

public class Patron {

//attributes
private String name = null;
private int cardNumber = 0;

//operations
public Patron (String name, int cardNumber){
    this.name = name;
    this.cardNumber = cardNumber;
}

public String getName(){
    return name;

}

public int getCardNumber(){
    return cardNumber;
}
public int addPatron(String name) throws PatronException {
    int maxKey = -1;

    for (Map.Entry<Integer, Patron> entry : patrons.entrySet()) {
        if (entry.getValue().getName().equals(name)) {
            // TODO: Consider using IllegalArgumentException
            throw new PatronException("This patron already exists");
        }
        maxKey = Math.max(maxKey, entry.getKey());
    }
    int newKey = maxKey + 1;
    Patron newPatron = new Patron(name, newKey);
    patrons.put(newKey, newPatron);
    return newKey;
}
public int addconsor(字符串名称)引发异常{
int maxKey=-1;
for(Map.Entry:customers.entrySet()){
if(entry.getValue().getName().equals(name)){
//todo:考虑使用非法语言异常
抛出新的用户异常(“此用户已存在”);
}
maxKey=Math.max(maxKey,entry.getKey());
}
int newKey=maxKey+1;
用户newPatron=新用户(名称,新密钥);
用户。put(新键,新用户);
返回newKey;
}

此外,听起来你真的需要一个从名字到用户的映射,可能还需要一个从id到用户的映射。

nameTest.getName()==name应该是nameTest.getName().equals(name)看起来你有一个映射,但你应该有一个映射。@DiegoBasch:应该有,但这不能解释测试失败的原因,由于使用了字符串文字(这将被扣留)。如果第一个条目与给定名称不同名,您还可以得出结论,即名称是唯一的。@JonSkeet这取决于用户的构造函数正在做什么。但是!=对于not equals仍然可以吗?不,您应该使用if(!(nameTest.getName().equals(name))。更好的是,使用else。它等于或不等于,没有其他选项。您可以信任JVM。:
=
对于非原语有效-它对于引用有非常特定的含义(检查引用标识)。另外,
Map
没有使用
Patron
作为键,因此
hashCode
equals
在这里是不相关的。在我的定义中,允许但不会返回此类型比较的预期结果(在本例中)是无效的。有时使用简单的词语,提供更好的理解。关于hashCode和equals。它们可能与代码示例无关,但可能更容易解决OP遇到的问题。但无论如何,在SO规则中,否决票更有效;-)。任何东西都只能根据要求被视为有效或无效。在某些情况下,将引用与
=
进行比较正是您想要的。我同意这在这里不合适,但我仍然不会声称使用
=
是“无效的”。@JonSkeet,你是对的,但我认为你认为我不知道操作符是如何工作的。我承认,在整个描述中,缺乏对你们所知的人的上下文可能导致这种解释。但我并没有删除这篇文章的唯一原因是,我想知道如何使用运算符==来表示字符串比较操作?我想确切地说它的作用是:它比较对象标识的引用。这通常不是您想要的,但它仍然是一个有效的运算符。它不像是有未定义的行为或类似的东西。我对你所知道的不加评论——我只能评论你所写的。这种改变正是我们所需要的+1+1+1:)