2013-09-01 3 views
2

У меня есть приложение для Android, основным компонентом которого является HashMap<String,float[]>. Система имеет высокий уровень параллелизма. например вот следующие три ситуации, у меня есть, которые происходят часто и они сильно перекрываются в природеЭффективно использовать ConcurrentHashMap?

  1. перебрать все ключи в HashMap и сделать некоторые операции на его значение (только для чтения операции).
  2. Добавить новый ключ, пары значений в Hashmap.
  3. Удалить некоторые ключи из Hashmap.

Я делаю все эти операции в разных потоках и, таким образом, я с помощью ConcurrentHashMap , поскольку некоторые несоответствия в извлечениях не имеет значения. например, При повторном использовании карты, если новые записи добавлены, не имеет значения, чтобы сразу не читать эти новые значения, поскольку я гарантирую, что в следующий раз они будут прочитаны.

Кроме того, при удалении записи я воссоздании итератора каждый раз, чтобы избежать «ConcurrentModificationException»

Предположим, существует следующая HashMap (т.е. ConcurrentHashMap)

ConcurrentHashMap<String,float[]> test=new ConcurrentHashMap<String, float[]>(200); 

Теперь Retrieval я следующее

Iterator<String> reader=test.keySet().iterator(); 
      while(reader.hasNext()) 
      { 
       String s=reader.next(); 
       float[] temp=test.get(s); 
       //do some operation with float[] temp here(read only operation) 
      } 

и для удаления я следующее

boolean temp = true; 
     while (temp) { 
      for (String key : test.keySet()) { 
       temp = false; 
       if (key.contains("abc")) { 
        test.remove(key); 
        temp = true; 
        break; 
       } 
      } 
     } 

и при вставке новых значений Я просто делаю

test.put("temp value", new float[10]); 

Я не уверен, что его очень эффективное использование. Также важно не читать удаленные значения (однако мне нужна эффективность, и поскольку итератор снова создается во время вызова функции, он гарантирует, что в следующий раз я не получу удаленные значения), так что может возникнуть большая несогласованность терпимо?

Может ли кто-нибудь сказать мне эффективный способ сделать это?

PS. Я забыл упомянуть, почему я делаю операцию по удалению таким образом. я сейчас изменяет свое состояние, на котором он был удалено из равных содержит (может быть несколько укусов, имеющих префикс «ABC», а затем различными суффиксами. Так что мне нужно, чтобы удалить все те, а затем.

+0

Это, безусловно, неэффективно, чтобы перебрать всю карту, чтобы удалить одну запись. Почему бы вам просто не позвонить remove ("abc")? – EJP

+0

Да, к сожалению, я изменил условие удаления на содержащийся. –

+0

Нет, вы должны изменить весь блок на один вызов remove(). Тебе ничего не нужно, и я не понимаю, почему ты думаешь иначе. -1 – EJP

ответ

4

перебрать все ключи в HashMap и сделать некоторая операция по его значению (операции только для чтения).

Не перебрать набор ключей, чтобы затем извлечь значения тоже - перебрать записи установлен непосредственно:

for (Map.Entry<String, float[]> e : map.entrySet() { 
    String key = e.getKey(); 
    float[] value = e.getValue(); 
    //do something with them 
} 

Это более эффективно в целом (даже для «нормальных» HashMaps) , но это также уменьшит конфликт в вашем случае (вдвое больше доступа к карте).

Добавить новый ключ, пары значений в Hashmap.

Да это просто: map.put(s, f);

Удалить Некоторые ключи от Hashmap.

Если вам нужно проверить, что ключ содержит заданную подстроку, то вам нужно перебирать ключи, как вы делаете, хотя я не знаю, почему у вас есть время + для + перерыв вместо просто для.

+0

в порядке .. так что итерация по входу всегда быстрее? Я делаю это даже для операции удаления? –

+1

@DebarshiDutta Нет, это быстрее, если вам нужно получить доступ как к ключу, так и к значению - если вы только заботитесь о клавишах (например, при удалении), то итерация по keySet более эффективна. – assylias

+0

@ user1084563 Я этого не знал - спасибо. – assylias

2

Из-за пути вы используете ConcurrentHashMap, вы точно удаляя его Concurrent характеристики. Ваши попытки (ре) синхронизация будет работать очень часто, но не всегда.

Рассматривали ли вы покинуть keys в HashMap? Я имею в виду чего-то типа:

public static final float[] DELETED= new float[0] ; 

    /* delete */ 
    test.put(key,DELETED); 

    /* insert */ 
    test.put(key,value); 

    /* iterate */ 
    for(Map.Entry<String,float[]> e: test.entrySet) { 
     if(e.getValue() != DELETED) { 
      operateOn(e); 
     } 
    } 

Если ключи слишком летучие (т. через некоторое время у вас будет слишком много предметов DELETED), то вы можете создать очистку Thread.

0

Согласно API ConcurrentHashMap, его итераторы никогда не бросают ConcurrentModificationException, поэтому вам не нужно ломаться после удаления. Но в любом случае правильный путь для обхода и удалить этот

for (Iterator<String> i = test.keySet().iterator(); i.hasNext();) { 
    String next = i.next(); 
    if (next.equals("abc")) { 
      i.remove(); 
    } 
} 

таким образом, он будет работать даже с отказоустойчивостью быстро итераторов без ConcurrentModificationException

+0

Хорошо .. Я не смотрю тогда .. Я изменю это –

+0

Почему? Что случилось с вызовом метода remove()? – EJP

Смежные вопросы