-1

以下方法应该计算给定集合中每个项目的出现次数:

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

散列中的值更新超出了我打算做的,我不知道如何。

帮助表示赞赏。

4

2 回答 2

2

您似乎不小心AtomicInteger用不同的键重用了相同的值。当您将一个AtomicInteger放入地图时,它可以在您调用时重新使用get

这是发生了什么:

输入:AAA

它尚不存在,因此one放置在地图中。

输入:A

它尚不存在,因此one放置在地图中。地图中现在有两个引用one

输入:AA

它尚不存在,因此one放置在地图中。地图中现在有三个引用one

输入:B

它尚不存在,因此one放置在地图中。地图中现在有四个引用one

输入:A

A已存在,因此检索该值。现在count指的是同一个对象onecount递增,但会生成一个副本。现在AAA, AA, 和B仍然映射到原来的AtomicInteger, 但现在错了; 它是2。但是,A指的是第二个AtomicInteger,在 处是正确的2

输入:AAA

AAA已存在,因此检索该值。现在再次count引用与 相同的对象onecount递增,但会生成一个副本。现在,AAandB仍然映射到原来的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.
}
于 2013-11-13T00:52:59.113 回答
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);
于 2013-11-13T00:49:50.367 回答