2013-11-13 2 views
-1

Следующий метод должен считать вхождений каждого элемента в заданном наборе:Граф вхождения строки в строку [] с помощью Map <String, AtomicInteger>

void groupBy(String[] stuff) { 
LinkedHashMap<String, AtomicInteger> A = new LinkedHashMap<String, AtomicInteger>(); 

final AtomicInteger one = new AtomicInteger(1); 
AtomicInteger count; 

for (String key:stuff) { 
    count = A.get(key); 
    if (count==null) A.put(key, one); 
     else System.out.println("Previous value :"+A.put(key, new AtomicInteger(count.incrementAndGet()))); 
} 

    Set set = A.entrySet(); 
    Iterator ii = set.iterator(); 

    while(ii.hasNext()) { 
    Map.Entry me = (Map.Entry)ii.next(); 
    System.out.print(me.getKey() + ": "); 
    System.out.println(me.getValue()); 
    } 
} 

Итак, если я бегу он по парам

String a[] = {"AAA", "A", "AA", "B", "A", "AAA"}; 

я должен получить

Previous value :1 
Previous value :1 
AAA: 2 
A: 2 
AA: 1 
B: 1 

Но то, что я получаю

Previous value :2 
Previous value :3 
AAA: 3 
A: 2 
AA: 3 
B: 3 

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

помочь оценить.

+2

Любая конкретная причина, по которой вы использовали 'AtomicInteger'? Вы сделали простую программу очень сложной проблемой. – Prateek

+1

почему 'AtomicInteger'? – Trying

+0

@Prateek - Да. сделать приращение компактным. – user2985116

ответ

0

У вас есть проблемы при A.put(key, one); изменить его на A.put(key, new AtomicInteger(1)); и это будет работать

также, там действительно нет смысла в AtomicInteger, вы можете переписать код, как:

LinkedHashMap<String, Long> A = new LinkedHashMap<String, Long>(stuff.length); 
for (String key: stuff) 
    A.put(key, (A.containsKey(key)?A.get(key):0L)+1L); 
+0

Позвольте мне попробовать этот. – user2985116

2

Похоже, вы случайно повторно использовать то же значение AtomicInteger с разными ключами. Когда вы размещаете на карте AtomicInteger, его можно повторно использовать, когда вы вызываете get.

Вот что происходит:

Вход: AAA

Это еще не существует, поэтому one помещается на карте.

Вход:

Это еще не существует, поэтому one помещается на карте. На карте теперь есть две ссылки на one.

Вход: AA

Это пока не существует, поэтому one помещается на карте. На карте теперь есть три ссылки на one.

Вход: B

Это пока не существует, поэтому one помещается на карте. На карте теперь есть четыре ссылки на one.

Вход:

A уже существует, так что значение извлекается. Теперь count относится к тому же объекту, что и one! count увеличивается, но делается копия. Теперь AAA, AA и B по-прежнему отображаются на исходном AtomicInteger, но теперь это неправильно; это 2.Однако A относится ко второму AtomicInteger, что является правильным на 2.

Вход: AAA

AAA уже существует, так что значение извлекается. Теперь count относится к тому же объекту, что и one, еще раз! count увеличивается, но делается копия. Теперь AA и B все еще сопоставлены с оригиналом AtomicInteger, но теперь это неправильно; это 3. Однако A относится ко второму AtomicInteger, и он по-прежнему верен в 2. Кроме того, AAA относится к третьему AtomicInteger, но он по-прежнему не соответствует 3.

Решения

Изменение при создании новых AtomicInteger объектов, а только увеличивают, когда вам не нужны новые; они изменяемы.

for (String key : stuff) { 
    AtomicInteger count = A.get(key); 
    if (count == null) 
     A.put(key, new AtomicInteger(1)); 
    else 
     count.incrementAndGet(); // Modifies the object referred to in the map. 
} 
+0

это объясняет - и хорошо. пока еще нет. – user2985116

+0

Вы можете легко переключить принятый ответ на ответ, который помог наиболее эффективно понять и решить конкретную проблему. – BalusC