在 Java HashMap 中保留一对原语

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/903107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:52:09  来源:igfitidea点击:

Keeping a pair of primitives in a Java HashMap

javahashmapprimitivekeyvaluepair

提问by zeroin23

I have a list of files. I would like to scan through and keep a count of the number of files with the same size. the issue is with filesize which is a long, as we know, hashmap will take in only an object and not a primitive. So using new Long(filesize), I put it into the hashmap. instead of getting a pair of (filesize, count), I got a list of (filesize, 1) due to the fact that each Long obj is unique.

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

How do I go about building this accumulator?

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

Any solution for 1.4.2?

1.4.2的任何解决方案?

回答by cletus

You simply do it this way:

你只需这样做:

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);
  }
}

There is some auto-boxingand unboxing going on here.

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

回答by Peter Lawrey

or you could use AtomicInteger as a mutable integer.

或者您可以使用 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();
  }
}

回答by Chii

Instead of using new Long(size), you should use Long.valueOf(size). that will return the same Long reference that is internally cached, and should also boost performance (not that it will be visible unless you do millions of these new Long()operations).

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

ps. only works for java 1.5 or above

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

回答by ldog

Expanding on what cletus wrote.

扩展 cletus 所写的内容。

His solution is fine, except it only stores each filesize that you come across and the number of files that have this size. If you ever want to know which files those are this data structure will be useless to you so I don't think cletus solution is quite complete. Instead I would do

他的解决方案很好,除了它只存储您遇到的每个文件大小以及具有此大小的文件数量。如果您想知道哪些文件是这种数据结构对您来说毫无用处,所以我认为 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);
} 

then you can get the number of files with c.size() and you can iterate through all the files with that number easily without having to run this procedure again.

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

回答by Hyman Leow

I think there's more to this, and we'll need more details from you. I'm assuming you know there's definitely more than one file of a given size, otherwise I'd first check to see that that's the case. For all you know, you simply have a lot of files with unique file sizes.

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

You mentioned:

你提到:

...due to the fact that each Long obj is unique.

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

I don't think this is the problem. While this may be true depending on how you are instantiating the Longs, it should not prevent HashMaps from behaving the way you want. As long as the two key objects return the same hashCode() value, and the equals() method say they are equal, your HashMap will not create another entry for it. In fact, it should not be possible for you to see "a list of (filesize, 1)" with the same filesize values (unless you wrote your own Long and failed to implement hashCode()/equals() correctly).

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

That said, Cletus' code should work if you're using Java 5 or higher, if you're using Java 1.4 or below, you'll need to either do your own boxing/unboxing manually, or look into Apache Commons Collections. Here's the pre-Java 5 version of Cletus' example:

也就是说,如果您使用的是 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));
  }
}

回答by adrian.tarau

You can use Troveto store pairs (long,int) - TLongIntHashMap

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