在Java HashMap中保留一对原语

问题描述 投票:6回答:6

我有一个文件列表。我想扫描并保持相同大小的文件数量。问题是文件大小很长,正如我们所知,hashmap只接受一个对象而不是一个基元。所以使用new Long(filesize),我把它放入hashmap。由于每个Long obj都是唯一的,因此我得到了一个(filesize,1)列表,而不是得到一对(filesize,count)。

我该如何构建这个累加器?

1.4.2的任何解决方案?

java hashmap primitive keyvaluepair
6个回答
15
投票

你只需这样做:

Map<Long, Integer> count = new HashMap<Long, Integer>();
for (File file : files) {
  long size = file.getTotalSpace();
  Integer n = count.get(size);
  if (n == null) {
    count.put(size, 1);
  } else {
    count.put(size, n + 1);
  }
}

这里有一些auto-boxing和拆箱。


6
投票

而不是使用new Long(size),你应该使用Long.valueOf(size)。这将返回内部缓存的相同Long引用,并且还应该提高性能(除非您执行数百万次new Long()操作,否则它将是可见的)。

PS。仅适用于java 1.5或更高版本


4
投票

您可以使用Trove来存储对(long,int) - TLongIntHashMap


3
投票

或者您可以使用AtomicInteger作为可变整数。

Map<Long, AtomicInteger> count = new HashMap<Long, AtomicInteger>();
for (File file : files) {
  long size = file.length(); // getTotalSpace() get the space consumed (e.g. a multiple of 8K) rather the actual file size.
  AtomicInteger n = count.get(size);
  if (n == null) {
    count.put(size, new AtomicInteger(1));
  } else {
    n.getAndIncrement();
  }
}

1
投票

扩大了克莱特斯写的内容。

他的解决方案很好,除了它只存储你遇到的每个文件大小和具有这个大小的文件数。如果您想知道哪些文件对于您来说这些数据结构将毫无用处,那么我认为cletus解决方案并不完整。相反,我会这样做

Map<Long, Collection<File>> count = new HashMap<Long, Collection<File>>();
for (File file : files) {
long size = file.getTotalSpace();
Collection<File> c = count.get(size);
if (c == null) {
    c = new ArrayList<File>(); //or whatever collection you feel comfortable with
    count.put(size, c);
}
    c.add(file);
} 

然后你可以使用c.size()获得文件数量,并且可以轻松地遍历所有具有该数字的文件,而无需再次运行此过程。


1
投票

我认为还有更多内容,我们需要您提供更多详细信息。我假设你知道肯定有一个给定大小的文件,否则我首先要检查是否是这种情况。如你所知,你只需拥有大量具有独特文件大小的文件。

你提到过:

...由于每个Long obj都是独一无二的。

我不认为这是问题所在。虽然这可能是真的,这取决于你如何实例化Longs,但它不应该阻止HashMaps按照你想要的方式运行。只要两个键对象返回相同的hashCode()值,并且equals()方法声明它们相等,您的HashMap就不会为它创建另一个条目。实际上,您应该不可能看到具有相同文件大小值的“(filesize,1)列表”(除非您编写了自己的Long并且未能正确实现hashCode()/ equals())。

也就是说,如果您使用的是Java 5或更高版本,Cletus的代码应该可以工作,如果您使用的是Java 1.4或更低版本,您需要手动执行自己的装箱/拆箱,或者查看Apache Commons Collections。这是Cletus的例子的Java 5之前的版本:

Map count = new HashMap();
for (Iterator filesIter = files.iterator(); filesIter.hasNext();) {
  File file = (File)filesIter.next();
  long size = file.getTotalSpace();
  Integer n = count.get(size);
  if (n == null) {
    count.put(size, Integer.valueOf(1));
  } else {
    count.put(size, Integer.valueOf(n.intValue() + 1));
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.