自定义Java类与映射的速度

自定义Java类与映射的速度,java,runtime,Java,Runtime,哪个更快: 一种集合,其元素均为自定义对象的实例,定义如下: public class CustomObject{ private static String A; private static String B; private static String C; public static String getA(){ return A; } public static getB(){ return B;

哪个更快:

  • 一种
    集合
    ,其元素均为
    自定义对象的实例,定义如下:

    public class CustomObject{
    
        private static String A;
        private static String B;
        private static String C;
    
        public static String getA(){
            return A;
        }
    
        public static getB(){
            return B;
        }
    
        public static getC(){
            return C;
        }
    }
    
  • 一个
    集合
    ,其元素都是
    映射
    的实例,其中每个映射的格式都是
    {“a”:Avalue,“B”:Bvalue,“C”:Cvalue}

  • 或者任何其他可以更好地捕获这些数据的数据结构

  • 如果我想得到属性为/key a==“somevalue”的所有对象/贴图的子集

    您可以使用或任何其他库。此外,如果集合较大,答案是否会改变


    编辑:我的一位同事告诉我,自定义类的运行时比hashmap快——为什么会有人使用hashmap,然后?

    如果您在重复搜索哪些集合包含特定属性的值时寻求最佳运行时性能,那么您需要使用数据库(或内存中的数据库)或手动取消规范化数据,以便维护每个属性的列表映射,并按其值设置键请注意,只有在这些查找足够频繁且性能足够关键以保证数据复制成本的情况下,此解决方案才有价值。

    例如

    //aSets是所有具有
    //字段“_a”的指定值(值为映射键)
    映射ASET;
    地图BSET;
    ...
    
    这并不理想,但它提供了所需的查找

    编写一个索引器类来自动创建这些映射并不太困难,它使用所提供集合的底层对象上的反射。不久前,我写了一些代码来做类似的事情,作为某种事物的概念证明。从未使用过,但一直保留着。。。这是未注释的,使用风险由您自己承担(它不适用于编写的集合,但很容易修改):

    公共类索引器
    {
    私有映射索引=新的HashMap();
    公共void添加(对象)引发异常
    {
    BeanInfo info=Introspector.getBeanInfo(object.getClass());
    PropertyDescriptor[]propertyDescriptors=info.getPropertyDescriptors();
    for(PropertyDescriptor描述符:propertyDescriptors)
    {
    String fieldName=descriptor.getName();
    Map Map=index.get(fieldName);
    if(map==null)
    {
    map=新的HashMap();
    index.put(字段名、地图);
    }
    Method=descriptor.getReadMethod();
    对象数据=方法.invoke(对象);
    Set=map.get(数据);
    if(set==null)
    {
    set=新的HashSet();
    map.put(数据,集合);
    }
    集合。添加(对象);
    }
    }
    公共集获取(字符串字段名、对象值)
    {
    Map Map=index.get(fieldName);
    if(map!=null)
    {
    Set=map.get(值);
    如果(设置!=null)
    {
    返回集合。不可修改集合(集合);
    }
    }
    返回null;
    }
    公共静态类测试
    {
    私有字符串值1;
    私有字符串值2;
    公共整数;
    公共测试(字符串v1、字符串v2、整数n)
    {
    值1=v1;
    值2=v2;
    数字=n;
    }
    公共字符串getValue1()
    {
    返回值1;
    }
    public void setValue1(字符串值1)
    {
    此值为1.value1=value1;
    }
    公共字符串getValue2()
    {
    返回值2;
    }
    public void setValue2(字符串值2)
    {
    此参数为0.value2=value2;
    }
    @凌驾
    公共字符串toString()
    {
    返回“Test[value1=“+value1+”,value2=“+value2+”,number=“+number+””;
    }
    }
    公共静态void main(字符串[]args)引发异常
    {
    测试1=新测试(“蓝色”、“狗”5);
    测试2=新测试(“蓝色”、“cat”,10);
    测试3=新测试(“绿色”、“鸭形”,10);
    Indexer Indexer=新索引器();
    添加索引器(test1);
    添加索引器(test2);
    添加索引器(test3);
    System.out.println(“get value1=blue:\n”+indexer.get(“value1”,“blue”);
    System.out.println(“\nget value1=green:\n”+indexer.get(“value1”,“green”);
    System.out.println(“\nget number=5:\n”+indexer.get(“number”,5));
    System.out.println(“\nget number=10:\n”+indexer.get(“number”,10));
    }
    }
    
    我假设我们正在将
    Map
    与等效的自定义类型进行比较,如下所示:

    public class CustomObject {
        private String a, b, c;
    
        public CustomObject(String a, String b, String c) {
            this.a = a; this.b = b; this.c = c;
        }
        public String getA() { return a; }
        public String getB() { return b; }
        public String getC() { return c; }
    }
    
    如果我们正在比较的操作是
    obj.getA()
    map.get(“A”)
    ,那么定制映射将更快,可能会快1到2个数量级。对快多了

    另一方面,如果我们将
    CustomObject
    实例放入一组“混合类型”对象中,我们对这些对象的字段一无所知,那么调用
    getA
    会变得更加困难/昂贵,
    Map
    解决方案当然也会更简单、更快。(这取决于您可以做出的假设。)


    此外,如果集合较大,答案是否会改变

    不会。它不会显著改变性能特征


    那么,为什么会有人使用hashmap呢

    最好/有必要使用
    Map
    的用例是编译时可能的键集未知的情况。这意味着您不能将
    CustomClass
    作为一个普通的类来编写手工编写的源代码

    事实上,在大多数情况下,这两种方法的相对代码简单性和健壮性应该决定您采用的方法。如果键是静态的,则
    public class Indexer
    {
        private Map<String,Map<Object,Set<Object>>> index = new HashMap<String,Map<Object,Set<Object>>>();
    
        public void add(Object object) throws Exception
        {
            BeanInfo info = Introspector.getBeanInfo(object.getClass());
    
            PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : propertyDescriptors)
            {
                String fieldName = descriptor.getName();
                Map<Object,Set<Object>> map = index.get(fieldName);
                if (map == null)
                {
                    map = new HashMap<Object,Set<Object>>();
                    index.put(fieldName, map);
                }
                Method method = descriptor.getReadMethod();
                Object data = method.invoke(object);
                Set<Object> set = map.get(data);
                if (set == null)
                {
                    set = new HashSet<Object>();
                    map.put(data, set);
                }
                set.add(object);
            }
    
        }
    
        public Set<Object> get(String fieldName, Object value)
        {
            Map<Object,Set<Object>> map = index.get(fieldName);
            if (map != null)
            {
                Set<Object> set = map.get(value);
                if (set != null)
                {
                    return Collections.unmodifiableSet(set);
                }
            }
    
            return null;
        }
    
    
        public static class Test
        {
            private String value1;
            private String value2;
            public int number;
    
            public Test(String v1, String v2, int n)
            {
                value1 = v1;
                value2 = v2;
                number = n;
            }
    
            public String getValue1()
            {
                return value1;
            }
    
            public void setValue1(String value1)
            {
                this.value1 = value1;
            }
    
            public String getValue2()
            {
                return value2;
            }
    
            public void setValue2(String value2)
            {
                this.value2 = value2;
            }
    
    
            @Override
            public String toString()
            {
                return "Test [value1=" + value1 + ", value2=" + value2 + ", number=" + number + "]";
            }
    
    
        }
    
        public static void main(String[] args) throws Exception
        {
            Test test1 = new Test("blue", "dog", 5);
            Test test2 = new Test("blue", "cat", 10);
            Test test3 = new Test("green", "duck", 10);
    
            Indexer indexer = new Indexer();
            indexer.add(test1);
            indexer.add(test2);
            indexer.add(test3);
    
            System.out.println("get value1 = blue: \n" + indexer.get("value1", "blue"));
            System.out.println("\nget value1 = green: \n" + indexer.get("value1", "green"));
            System.out.println("\nget number = 5: \n" + indexer.get("number", 5));
            System.out.println("\nget number = 10: \n" + indexer.get("number", 10));
    
        }
    
    }
    
    public class CustomObject {
        private String a, b, c;
    
        public CustomObject(String a, String b, String c) {
            this.a = a; this.b = b; this.c = c;
        }
        public String getA() { return a; }
        public String getB() { return b; }
        public String getC() { return c; }
    }