2012-07-30 113 views
2

一些背景知识,以什么我想要实现:有效地名称访问域

我解析JSON(超过15GB),我必须将它存储在内存中,所以任何包装和额外的数据不欢迎,由于其中使用的框架和接口,我必须提供按名称访问字段的功能。通过用Enum替换一些String,用int替换Integer,用Double替换Double等,我能够削减大约90%的内存占用(与Jackson相比)。

我正在寻找在运行时以Java名义高效地访问字段。我意识到反思,但对我的情况来说,它的表现简直无法接受,所以我不想使用它。

如果它使得问题更容易解决,我不会太麻烦设置字段值。我也在编译时知道支持的字段的名称。

由于盒装对象的内存占用,我不想在地图中存储所有内容,但我不介意以盒装形式返回它们。

我确定他人遇到了这个问题,我对任何聪明的解决方案都感兴趣 - 比如果... else ...语句更聪明。

假设实现该接口是:

public interface Accessor { 
    Object get(String fieldName); 
} 

Object由get返回可以是任何类型,包括枚举。一个天真的实现将是:

public class TestObject implements Accessor { 

    public enum MyEnum {ONE, TWO, THREE}; 

    private final MyEnum myEnum; 
    private final int myInt; 
    private final double myDouble; 
    private final String myString; 

    public TestObject(MyEnum myEnum, int myInt, double myDouble, String myString) { 
     this.myEnum = myEnum; 
     this.myInt = myInt; 
     this.myDouble = myDouble; 
     this.myString = myString; 
    } 

    @Override 
    public Object get(String fieldName) { 
     if ("myEnum".equals(fieldName)) { 
      return myEnum; 
     } else if ("myInt".equals(fieldName)) { 
      return myInt; 
     } else if ("myDouble".equals(fieldName)) { 
      return myDouble; 
     } else if ("myString".equals(fieldName)) { 
      return myString; 
     } else { 
      throw new UnsupportedOperationException(); // Or could simply return null 
     } 
    } 

} 
+1

你想要动态访问字段,而不反射?你不能把这些值放到带有字段名称键的映射中,它必须访问一个对象?在运行时生成代码/字节码怎么样?除此之外,我不清楚你认为选择是什么。 – 2012-07-30 21:51:43

+0

什么是底层对象? – maasg 2012-07-30 21:57:01

+0

感谢您的问题。通过提供有关该问题的更多信息来回答他们。 – Artur 2012-07-30 22:13:49

回答

4

你想要的是从fieldName到一个值,该值的类型是由fieldName确定的映射。您预先知道一组字段名称,因此对于Enum这是一项理想的任务。

如果您不喜欢将每个字段硬编码为枚举的想法,那么变体将是枚举类型(MY_FIELD1变为MY_ENUM),并且具有从fieldName到此EnumType的映射。

在下面的代码中,我正在假设fieldName和TestObject之间的关系。具体来说,它看起来像TestObject呈现各种类型的相同的值(当然在合理的地方),而不是每个字段名称的单独值?

所以,代码:


重写:

@Override 
public Object get(String fieldName) { 
    MyField field = MyField.mapNameToField(fieldName); 
    if (field == null) 
     throw new UnsupportedOperationException(); // Or could simply return null 
    return field.getValue(this); 
} 

鉴于(类似):

enum MyField { 
    MY_FIELD1("myField1") { 
     public Object getValue(TestObject obj) { return obj.myEnum; } 
    }, 
    MY_FIELD2("myField2") { 
     public Object getValue(TestObject obj) { return obj.myInt; } 
    }, 
    ... 
    ; 

    public abstract Object getValue(TestObject obj); 
    public String getName() { return name; } 

    public static MyField mapNameToField(String name) { return map.get(name); } 

    static { 
     map = new HashMap<String,MyField>(); 
     for(MyField value: values()) { 
      map.put(value.getName(), value); 
     } 
    } 

    private MyField(String fieldName) { name = fieldName; } 

    private String name; 
    private static Map<String, MyField> map; 
} 
0

我从未使用过这一点,但看起来很有希望:

http://labs.carrotsearch.com/download/hppc/0.4.1/api/

“高性能原始集合(HPPC)库提供了为所有Java基元类型(字节,整型等)生成的典型数据结构(列表,堆栈和映射),以节省内存并提高性能。“

特别,对象{类型} OpenHashMap类可能是你在找什么:

  1. ObjectByteOpenHashMap
  2. ObjectCharOpenHashMap
  3. ObjectDoubleOpenHashMap
  4. ObjectFloatOpenHashMap
  5. ObjectIntOpenHashMap
  6. ObjectLongOpenHashMap
  7. ObjectShortOpenHashMap

我想你会的这些定义字段(或任何他们的子集,你喜欢)的所有7,你会探索每一个反过来看,如果关键是目前该类型的原始值。例如,

if (byteMap.containsKey(key)) { 
    return byteMap.lget(); // last value saved in a call to containsKey() 
} else if (charMap.containsKey(key)) { 
    return charMap.lget(); 
} else if { 
    // and so on... 
} 

通知他们有自己的特殊lget()方法调用优化的containsKey()/ get()方法的使用模式与地图太典型了。