简体   繁体   English

如何从Java的哈希图中删除String数组值?

[英]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. 我有一个1993年至2009年诺贝尔奖获得者的哈希图,关键是年份,值是获奖者姓名的字符串数组。 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. 某些年份的获胜者不止一个,而没有年份的年份不超过3。我正在尝试一种从哈希图中删除特定名称并删除密钥的方法,前提是该特定年份只有一位获胜者。 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) (例如,1993年的获奖者是纳尔逊·曼德拉和弗雷德里克·威廉·德·克莱克,如果我尝试只删除纳尔逊·曼德拉,那么1993年的全部作品都消失了)

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(); 您正在执行it.remove(); which will remove the entire entry (key-value pair) from the HashMap and not just the specific winner from the value. 它将从HashMap中删除整个条目(键值对),而不是从值中删除特定的获胜者。

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 如果值是字符串List ,这将起作用

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

If the values are array 如果值是array

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

this it.remove(); 这个it.remove(); will remove the entire key value pair 将删除整个键值对

update : 更新:

Download and import org.apache.commons.lang3 下载并导入org.apache.commons.lang3

To download Jar: http://www.java2s.com/Code/Jar/c/Downloadcommonlang3jar.htm 要下载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. 您的变量“ it”指向每个包含年份键和名称列表的地图条目。 If you call it.remove(), you're removing the entire map entry. 如果调用它。remove(),则将删除整个地图条目。 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. 如果有一个名字,那么调用它是正确的。remove()会删除所有内容。 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. 作为一般规则,如果您发现自己不得不经常添加或删除对象,我建议您使用列表或集合而不是数组,这仅仅是因为从旧的数组创建新数组仍然需要转换为列表,所以您d优化这些步骤。

it is map entry iterator, so it.remove() will remove the whole entry (mapping of key to list of authors). it是地图条目迭代器,因此it.remove()将删除整个条目(键映射到作者列表)。 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. 您应该使用List<String>作为获奖者列表,而不是String[] ,因为它更易于操作。

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

}

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

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