6

我有一个文件列表。我想扫描并计算相同大小的文件数量。问题在于文件大小很长,正如我们所知,hashmap 将只接收一个对象而不是一个原语。所以使用new Long(filesize),我将其放入哈希图中。由于每个 Long obj 都是唯一的,我没有得到一对 (filesize, count),而是得到了 (filesize, 1) 的列表。

我该如何构建这个蓄能器?

1.4.2的任何解决方案?

4

6 回答 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);
  }
}

这里有一些自动装箱和拆箱。

于 2009-05-24T05:03:52.147 回答
6

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

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

于 2009-05-24T09:02:23.690 回答
4

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

于 2009-05-25T00:30:34.010 回答
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();
  }
}
于 2009-05-24T08:59:20.297 回答
1

扩展 cletus 写的内容。

他的解决方案很好,除了它只存储您遇到的每个文件大小以及具有此大小的文件的数量。如果您想知道哪些文件是这种数据结构,那么这些文件对您来说毫无用处,所以我认为 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() 获取文件的数量,并且您可以轻松地遍历具有该数量的所有文件,而无需再次运行此过程。

于 2009-05-24T09:08:13.930 回答
1

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

你提到:

...因为每个 Long 对象都是独一无二的。

我不认为这是问题所在。虽然这可能取决于您如何实例化 Long,但它不应该阻止 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));
  }
}
于 2009-05-24T10:11:21.557 回答