代码之家  ›  专栏  ›  技术社区  ›  java.is.for.desktop

Java集合:当“size”超过“int”时会发生什么?

  •  7
  • java.is.for.desktop  · 技术社区  · 16 年前

    Integer 他变成了一个 HashSet .

    Collection.size()

    编辑: 解决了的: 集合.大小() 退货 Integer.MAX 超过整数范围时。
    那么,如何确定集合中元素的“真实”计数呢?

    注1: 抱歉,这可能是一个让我为您搜索它的问题,但我真的没有找到任何东西;)

    注2: reference + cached_hashcode + boxed_integer_object + real_int_value ,对吧?

    VisualVM

    对于那些关心的人:

    import java.util.*;
    import java.lang.management.*;
    
    public final class _BoxedValuesInSetMemoryConsumption {
      private final static int MILLION = 1000 * 1000;
    
      public static void main(String... args) {
        Set<Integer> set = new HashSet<Integer>();
    
        for (int i = 1;; ++i) {
          if ((i % MILLION) == 0) {
            int milsOfEntries = (i / MILLION);
            long mbytes = ManagementFactory.getMemoryMXBean().
                getHeapMemoryUsage().getUsed() / MILLION;
            int ratio = (int) mbytes / milsOfEntries;
            System.out.println(milsOfEntries + " mil, " + mbytes + " MB used, "
                + " ratio of bytes per entry: " + ratio);
          }
    
          set.add(i);
        }
      }
    }
    

    执行参数:

    在opensuse11.3x64下使用jdk7build105的x64版本进行测试。

    -XX:+UseCompressedOops -Xmx2048m
    

    输出结果:

    1 mil, 56 MB used,  ratio of bytes per entry: 56
    2 mil, 113 MB used,  ratio of bytes per entry: 56
    3 mil, 161 MB used,  ratio of bytes per entry: 53
    4 mil, 225 MB used,  ratio of bytes per entry: 56
    5 mil, 274 MB used,  ratio of bytes per entry: 54
    6 mil, 322 MB used,  ratio of bytes per entry: 53
    7 mil, 403 MB used,  ratio of bytes per entry: 57
    8 mil, 452 MB used,  ratio of bytes per entry: 56
    9 mil, 499 MB used,  ratio of bytes per entry: 55
    10 mil, 548 MB used,  ratio of bytes per entry: 54
    11 mil, 596 MB used,  ratio of bytes per entry: 54
    12 mil, 644 MB used,  ratio of bytes per entry: 53
    13 mil, 827 MB used,  ratio of bytes per entry: 63
    14 mil, 874 MB used,  ratio of bytes per entry: 62
    15 mil, 855 MB used,  ratio of bytes per entry: 57
    16 mil, 902 MB used,  ratio of bytes per entry: 56
    17 mil, 951 MB used,  ratio of bytes per entry: 55
    18 mil, 999 MB used,  ratio of bytes per entry: 55
    19 mil, 1047 MB used,  ratio of bytes per entry: 55
    20 mil, 1096 MB used,  ratio of bytes per entry: 54
    21 mil, 1143 MB used,  ratio of bytes per entry: 54
    22 mil, 1191 MB used,  ratio of bytes per entry: 54
    23 mil, 1239 MB used,  ratio of bytes per entry: 53
    24 mil, 1288 MB used,  ratio of bytes per entry: 53
    25 mil, 1337 MB used,  ratio of bytes per entry: 53
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    

    最后,使用了大约2 GiB的实际内存,而不是显示的1.3 GiB,因此每个条目的消耗是 更大 超过53字节。

    4 回复  |  直到 16 年前
        1
  •  6
  •   Joachim Sauer    16 年前

    你的问题似乎与题目的内容大不相同。

    你已经回答了标题中的问题( Integer.MAX_VALUE long 当然)。

    如果你想储存 Set int 值的数量可以变得非常大,然后 BitSet 实际上可能是更好的实现:

    import java.util.*;
    import java.lang.management.*;
    
    public final class IntegersInBitSetMemoryConsumption {
      private final static int MILLION = 1000 * 1000;
    
      public static void main(String... args) {
        BitSet set = new BitSet(Integer.MAX_VALUE);
    
        for (int i = 1;; ++i) {
          if ((i % MILLION) == 0) {
            int milsOfEntries = (i / MILLION);
            long mbytes = ManagementFactory.getMemoryMXBean().
                getHeapMemoryUsage().getUsed() / MILLION;
            double ratio = mbytes / milsOfEntries;
            System.out.println(milsOfEntries + " mil, " + mbytes + " MiB used, "
                + " ratio of bytes per entry: " + ratio);
          }
    
          set.set(i);
        }
      }
    }
    

    这将产生一个固定大小的数据结构,它可以保存范围内的所有值,而不会改变大小和占用相对较少的内存(每个可能的值1位加上一些开销)。

    然而,这种方法有两个缺点:

    • 价值观
    • 它不能提供

    对象(可能是延迟分配的)来分别保持正值和负值范围,并为 接口。

        2
  •  14
  •   quantumSoup    16 年前

    记忆饥渴,自己做了个测试, 存储数百万个 Integers HashSet .

    public int size()

    返回此表中的元素数 收藏。如果这个集合 Integer.MAX_VALUE 元素,返回 Integer.MAX\u值 .

        3
  •  3
  •   Ido Weinstein    16 年前

    从源代码:

     /**
     * Returns the number of elements in this collection.  If this collection
     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
     * <tt>Integer.MAX_VALUE</tt>.
     * 
     * @return the number of elements in this collection
     */
    int size();
    
        4
  •  0
  •   fortran    16 年前

    对于任何真正的处理器体系结构,一般的答案都是你不能。原因很简单:分配的对象(至少1个字大小)不能多于可寻址内存。

    当然,考虑到JVM的虚拟特性,有一种情况是可能发生的。 int 将始终是32位有符号的,您可以在64位机器上实现并运行JVM,在64位机器上可以寻址超过2GB的内存。

    在这种情况下,文件告诉我们 Integer.MAX_INT i < col.size() 停止将永远运行(尽管我认为任何循环 2**31-1