以下方法应该计算给定集合中每个项目的出现次数:
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());
}
}
所以,如果我在param上运行它
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
散列中的值更新超出我打算做的,我不知道如何。
帮助表示赞赏。
答案 0 :(得分:2)
您似乎意外地使用不同的密钥重复使用相同的AtomicInteger
值。当您将AtomicInteger
放入地图时,可以在致电get
时重复使用。
这是发生了什么:
输入:AAA
它尚不存在,因此one
被放置在地图中。
输入:A
它尚不存在,因此one
放置在地图中。现在,地图中有one
的两个引用。
输入:AA
它尚不存在,因此one
放置在地图中。现在,地图中有one
的三个引用。
输入:B
它尚不存在,因此one
放置在地图中。现在,地图中有one
的四个引用。
输入:A
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.
}
答案 1 :(得分: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);