java 如何获得HashSet的初始容量?

edqdpe6u  于 2023-09-29  发布在  Java
关注(0)|答案(3)|浏览(89)

HashSet如何获得初始容量?

import java.util.*;
import java.lang.reflect.Field;
public class Demo
{
   static int getCapacity(ArrayList<?> l) throws Exception
   {
      Field dataField = ArrayList.class.getDeclaredField("elementData");
      dataField.setAccessible(true);
      return ((Object[]) dataField.get(l)).length;
   }
   public static void main(String args[])
   {
      ArrayList a = new ArrayList();
      System.out.println(getCapacity(a));
      HashSet h = new HashSet(); //in case HashSet what we do
      System.out.println(h.capacity());
   }
}

实际上,我们在HashSet类中没有容量方法。那么我们如何得到HashSet的容量呢?如何获取HashSet对象的初始容量?

e4yzc0pl

e4yzc0pl1#

HashSet不会暴露这些信息。如果需要,您可以自己设置初始容量(例如,HashSet h = new HashSet(22);)。javadoc表示默认容量为16
在内部,HashSet只是通过HashSet.map字段 Package HashMap。我认为您可以使用反射来获取map字段,然后询问它的初始容量。我不明白你为什么要这么做。

zengzsys

zengzsys2#

我们不能直接检索HashSet对象创建后的初始容量,因为初始容量没有公开为公共方法或属性。HashSet类不提供方法来查询初始化时设置的初始容量。

t5fffqht

t5fffqht3#

类似于问题中的代码已经为ArrayList做了什么;使用额外的步骤来检索存储在map变量中的Map

public static int getCapacity(HashSet<?> s) throws Exception {
        var mapField = HashSet.class.getDeclaredField("map");
        mapField.setAccessible(true);
        var map = mapField.get(s);

        var capMet = HashMap.class.getDeclaredMethod("capacity");
        capMet.setAccessible(true);
        var cap = capMet.invoke(map);

        return (Integer) cap;
   }

最终必须使用--add-opens=java.base/java.util=ALL-UNNAMED选项调用(请参见InaccessibleObjectException: module java.base does not "opens java.util" to unnamed module @61443d8f
使用反射很容易破坏-它高度依赖于实现(例如map变量可以重命名或替换其类型)-基于OpenJDK 21的代码。

相关问题