我在做作业时遇到了麻烦,事情是我有大约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);
}
}
}
}
答案 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即使是这样简单的问题的人,但是不要想推测这里的原因)