简体   繁体   中英

How to remove an String array value from within a hashmap in java?

I have a hashmap of nobel winners from 1993 - 2009, the key is the year and the value is an array of string of the winners names. Some years have more than one winner and no year has more than 3. I am trying a method to remove a specific name from the hashmap and to remove the key if there is only one winner for that specific year. When I try this method it removes the entire key and value, no matter if there were more than one winner in that year. (example in 1993 the winners are Nelson Mandela and Frederik Willem de Klerk, if i try to remove only Nelson Mandela, the entire entry from 1993 is gone)

public void removeWinner(String nameOfWinnerToRemove)

    {Iterator <HashMap.Entry<Integer, String[]>> it = winners.entrySet().iterator();
    while(it.hasNext())
    {
        HashMap.Entry<Integer, String[]> entry = it.next();
        for(int i = 0; i < entry.getValue().length; i++)

        {
            if(entry.getValue()[i].equalsIgnoreCase(nameOfWinnerToRemove))
            {
                it.remove();


            }
        }
    }

}

You are doing it.remove(); which will remove the entire entry (key-value pair) from the HashMap and not just the specific winner from the value.

You should do something like this:

if(entry.getValue()[i].equalsIgnoreCase(nameOfWinnerToRemove))
    {
        /* Prepare a new value string without the name you want to remove */
        it.put(/* Key */, /* New Value */); //Doing this will overwrite the entry so you don't have to remove and re-add
    }
  1. Create a new array of the un-matching winners
  2. Set the new array as the new value
  3. Remove the key-value-pair if the array has only one element.

It could be similar to the following (Replacing the array with a list for simpler use):

public void removeWinner(String nameOfWinnerToRemove) {
    final Map<String, List<String>> winnerMapping = new HashMap<>();
    final Iterator<Map.Entry<String, List<String>>> iterator = winnerMapping.entrySet().iterator();

    while (iterator.hasNext()) {
        final List<String> winners = iterator.next().getValue();
        final List<String> matchingWinners = new ArrayList<>();

        for (final String winner : winners) {
            if (winner.equalsIgnoreCase(nameOfWinnerToRemove)) {
                matchingWinners.add(winner);
            }
        }

        winners.removeAll(matchingWinners);

        if (winners.size() == 1) {
            iterator.remove();
        }
    }
}

simple to use this

myMap.get(yourKey).remove(yourValue);

more clear :

This would work if the value is List of strings

 winners.get(entry.getKey()).remove(nameOfWinnerToRemove);

If the values are array

 ArrayUtils.removeElement(winners.get(entry.getKey()), nameOfWinnerToRemove); 

this it.remove(); will remove the entire key value pair

update :

Download and import org.apache.commons.lang3

To download Jar: http://www.java2s.com/Code/Jar/c/Downloadcommonlang3jar.htm

Your variable "it" points to each map entry containing both the year key and the list of names. If you call it.remove(), you're removing the entire map entry. What you should do if you find the name in the array depends on how many names are in the list. If there is one name, then it is correct to call it.remove() since that removes everything. Otherwise, we want to have the map entry's value to hold a new array without that name.

Your code should look something like the following:

public void removeWinner(String nameOfWinnerToRemove) {
    Iterator <HashMap.Entry<Integer, String[]>> it = winners.entrySet().iterator();
    while(it.hasNext()) {
        HashMap.Entry<Integer, String[]> entry = it.next();
        List<String> namesList = new ArrayList<String>(Arrays.asList(entry.getValue()));

        // Enter here if found and removed name
        if(namesList.remove(nameOfWinnerToRemove)) {
            if(namesList.size() > 0) {
                // Set array without name
                entry.setValue(namesList.toArray(entry.getValue());
            } else {
                // New list is empty.  Remove entry.
                it.remove();
            }
        }
    }
}

As a general rule, I would suggest you use a List or Collection as opposed to an array if you find yourself having to often add or remove objects, simply because creating a new array from the old requires converting to a List anyway and so you'd be optimizing these steps.

it is map entry iterator, so it.remove() will remove the whole entry (mapping of key to list of authors). You need to only remove it if the list is empty, so this is a two-step process:

  1. Determine whether you need to remove the winner, and remove them if matching
  2. Whenever you remove a winner from a list, check whether you need to also remove the whole entry

You should use List<String> for the winners list instead of String[] , it is easier to manipulate.

Then you could use this approach:

public void removeWinner(String nameOfWinnerToRemove) {

    Iterator <HashMap.Entry<Integer, String[]>> it = winners.entrySet().iterator();
    while(it.hasNext()) {
        HashMap.Entry<Integer, String[]> entry = it.next();
        Iterator<String> listIt = entry.getValue().iterator();
        while (listIt.hasNext()) {
            String value = listIt.next();
            if(value.equalsIgnoreCase(nameOfWinnerToRemove)) {
                listIt.remove(); // remove the winner

            }
        }

        if (entry.getValue().isEmpty()) {
            it.remove(); // remove whole entry if empty
        }
    }

}

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