关于我想要实现的目标的一些背景:
我正在解析 JSON(超过 15GB),并且必须将其存储在内存中,因此不欢迎任何包装器和额外数据,由于其中使用的框架和接口(interface),我必须提供按名称访问字段的功能。通过将一些 String 替换为 Enum、Integer 替换为 int、Double 替换为 double 等,我能够减少大约 90% 的内存占用(与 Jackson 相比)。
我希望在运行时通过 Java 的名称有效地访问这些字段。我知道反射,但就我而言,它的性能根本 Not Acceptable ,所以我不想使用它。
如果它使问题更容易解决,我就不会太担心设置字段值。我还知道在编译时支持的字段的名称。
我不想将所有内容存储在 map 中,即 Map<String,Object>
由于盒装对象的内存占用,但我不介意以盒装形式返回它们。
我确信其他人也遇到过这个问题,并且我对任何聪明的解决方案感兴趣 - 比大量 if ... else ... 语句更聪明。
假设要实现的接口(interface)是:
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
}
}
}
最佳答案
您想要的是从 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;
}
关于java - 按名称有效访问字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11730112/