如何从ArrayList中同时删除多个项目

时间:2014-04-05 16:03:35

标签: java arraylist hashmap

我在做作业时遇到了麻烦,事情是我有大约40.000 HashMap<Character,Character>个对象存储在ArrayList<HashMap<Character,Character>>个对象中。

每个对象HashMap<Character,Character>对象代表替换密码的密钥。所以一个HashMap对象可能是:a->a; b->b; c->c; d->d; e->e; f->f; g->h; h->g 这意味着在编码/解密期间交换g和h。

问题是我正在对这个密码进行强力攻击编码,所以我循环遍历那些40.000密钥。

当程序检测到说g-&gt; h这是一个错误的替换时,我想删除包含该条目的所有HashMap对象,而不仅仅是我在循环中使用的当前元素,因此能够避免逐个检查密钥。

到目前为止,我已经尝试了以下内容,但它不会遇到异常或任何事情都没有完成,甚至在调试时都没有:

  ArrayList<HashMap<Character,Character>> all_keys = new ...`
  all_keys = generateAllCombinations();`
  ArrayList<HashMap<Character,Character>> keys_to_delete = new ...`

  for(HashMap<Character,Character> key:all_keys){`
     all_keys.removeAll(keys_to_delete);
     \\other stuff going on...`
        if (!letters[0].getChar().equals(Constants.CHAR_E)){
         Character invChar = key.get(Constants.CHAR_E);
          for(HashMap<Character,Character> key2 : all_keys){
                if(key2.get(Constants.CHAR_E).equals(invChar)){
                 keys_to_delete.add(key2);
                }
          }

    }
   }

2 个答案:

答案 0 :(得分:0)

使用Iterator。我的解决方案正在运行,但可能需要调整性能。

   Iterator<Map<String,String>> all_keys_iterator = all_keys.iterator();
   List<Map<String,String>> all_keys_new = new ArrayList<Map<String,String>> ();

   while(all_keys_iterator.hasNext()) {
    Map<String,String> copyMap = new HashMap<String,String> ();

    Map<String,String> all_keys_map = all_keys_iterator.next();
    for(String key: all_keys_map.keySet()) {
        if (!key.equalsIgnoreCase("key1")){
            copyMap.put(key, all_keys_map.get(key));
        }
    }
    if(!copyMap.isEmpty()) {
        all_keys_iterator.remove();
        all_keys_new.add(copyMap);
    }                      
   }

   all_keys.addAll(all_keys_new);

   for(Map<String,String> map: all_keys) {
    for(String key: map.keySet()) {
        System.out.println("key: " + key + " Value: " + map.get(key));
    }
   }

答案 1 :(得分:0)

已经提到过,从当前正在迭代的集合中删除元素时必须要小心。这可能很容易导致ConcurrentModificationException。对于&#34;复杂&#34;在你不能轻易使用迭代器的情况下,通常可以应用的模式是,而不是像

那样做
Collection<Element> collection = ...
for (Element element : collection)
{
    if (hasToBeRemoved(element)) 
    {
        // Will cause a ConcurrentModificationException!
        collection.remove(element);
    }
}

您收集要删除的元素,并立即删除它们

Collection<Element> collection = ...
Collection<Element> elementsToRemove = new List<Element>();
for (Element element : collection)
{
    if (hasToBeRemoved(element)) 
    {
        elementsToRemove.add(element);
    }
}
collection.removeAll(elementsToRemove);

根据该代码,您似乎尝试过使用keys_to_delete类似的内容,但这并不完全清楚。

正如评论中所提到的,您应该考虑替换的专用数据结构等。但即使您希望坚持列表和地图用于此目的,您也应始终使用 interface 。而不是

ArrayList<HashMap<Character,Character>> allKeys = ...

你应该写

List<Map<Character,Character>> allKeys = ... 

但是,关于实际问题:似乎可以通过引入类似computeKeysContaining(maps, entry)的方法来解决主要问题,该方法返回包含特定条目的给定集合中的所有映射。

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapListKeyRemoval
{
    public static void main(String[] args)
    {
        List<Map<Character,Character>> allKeys = generateAllCombinations();

        print("All keys", allKeys);

        Set<Map<Character,Character>> keysToDelete = 
            new LinkedHashSet<Map<Character,Character>>();
        for (Map<Character, Character> key : allKeys)
        {
            for (Entry<Character, Character> entry : key.entrySet())
            {
                if (isInvalidMapping(entry))
                {
                    System.out.println("Invalid mapping: "+entry);
                    Set<Map<Character, Character>> keysWithInvalidMapping =
                        computeKeysContaining(allKeys, entry);

                    print("Keys with invalid mapping", keysWithInvalidMapping);

                    keysToDelete.addAll(keysWithInvalidMapping);
                }
            }
        }
        print("Keys to delete", keysToDelete);

        allKeys.removeAll(keysToDelete);

        print("All keys after removal", allKeys);
    }

    private static void print(
        String message, Iterable<Map<Character,Character>> keys)
    {
        System.out.println(message);
        for (Map<Character, Character> key : keys)
        {
            System.out.println(key);
        }
    }

    private static Set<Map<Character, Character>> computeKeysContaining(
        List<Map<Character,Character>> allKeys,
        Entry<Character, Character> entry)
    {
        Set<Map<Character,Character>> keysContainingEntry =  
            new LinkedHashSet<Map<Character,Character>>();
        for (Map<Character, Character> key : allKeys)
        {
            Object value = key.get(entry.getKey());
            if (value != null && value.equals(entry.getValue()))
            {
                keysContainingEntry.add(key);
            }
        }
        return keysContainingEntry;
    }

    private static boolean isInvalidMapping(Entry<Character, Character> entry)
    {
        return entry.getKey().equals('g') && entry.getValue().equals('h');
    }

    private static List<Map<Character, Character>> generateAllCombinations()
    {
        List<Map<Character, Character>> result = 
            new ArrayList<Map<Character,Character>>();
        result.add(createMapping('f','i','r','s','t','-','g','h'));
        result.add(createMapping('s','e','c','o','n','d','g','x'));
        result.add(createMapping('t','h','i','r','d','-','g','h'));
        result.add(createMapping('f','o','u','r','t','h','g','x'));
        return result;
    }

    private static Map<Character, Character> createMapping(char ... c)
    {
        Map<Character, Character> map = 
            new LinkedHashMap<Character, Character>();
        for (int i=0; i<c.length/2; i++)
        {
            map.put(c[i*2+0], c[i*2+1]);
        }
        return map;
    }
}

(除此之外,我想知道为什么回答问题的人是那些(必须)创建https://stackoverflow.com/help/mcve即使是这样简单的问题的人,但是不要想推测这里的原因)