Iterating through hashmap and creating unique obje

2019-08-30 01:00发布

问题:

I explain what I am trying to do in comments above the parts in the method:

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;
}

When I try and run a simple unit test that will fail if I successfully add the same name for addPatron twice in a row, the test fails.

try {
    testLibrary.addPatron("Dude");
    testLibrary.addPatron("Dude");
    fail("This shouldn't have worked");

The test fails, telling me the addPatron method is able to use the same name twice.

@Jon Skeet:

My Patron class looks like this:

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;
}

}

回答1:

As others have said, the use of == for comparing strings is almost certainly inappropriate. However, it shouldn't actually have caused a problem in your test case, as you're using the same constant string twice, so == should have worked. Of course, you should still fix the code to use equals.

It's also not clear what the Patron constructor or getName methods do - either of those could cause a problem (e.g. if they create a new copy of the string - that would cause your test to fail, but would also be unnecessary usually).

What's slightly more worrying to me is this comment:

// 3. If the name is unique, we want to get the largest key value (customer number) 
// already in the hash, an increment by one.

This comment is within the main loop. So by that point we don't know that the name is unique - we only know that it doesn't match the name of the patron in this iteration.

Even more worrying - and I've only just noticed this - you perform the add within the iteration block too. It seems to me that you should have something more like this:

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;
}

Additionally, it sounds like really you want a map from name to patron, possibly as well as the id to patron map.



回答2:

You need to use equals to compare String objects in java, not ==. So replace:

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

with:

if (nameTest.getName().equals(name)) {


回答3:

Try to use

nameTest.getName().equals(name)

instead of

nameTest.getName() == name

because now you're comparing references and not the value of the String. it's explained here

Took another look on your code

Well i took another look on your code and the problem is, that your HashMap is empty at the start of the Test. So the loop will never be runned ==> there will never bee a Patron added or an Exception thrown.



回答4:

The cause of the problem is how you have used the compare operator ==.

When you use this operator against two objects, what you test is that variable point to the same reference.

To test two objects for value equality, you should use equals() method or compareTo if available.

For String class, invoke of equals is sufficient the check that the store same characters more.

What is equals method ?

To compare the values of Object The problem is how you compare names.



标签: java hashmap