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