java - 按名称有效访问字段

标签 java performance optimization

关于我想要实现的目标的一些背景:

我正在解析 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/

相关文章:

performance - 多余的限定符有什么缺点吗?有什么好处吗?

c++ - 插入排序优化

c++ - 测试虚函数的开销

algorithm - 最优和差

java - Snakeyaml 似乎不必要地将简单值包装在列表中

java - Slick2D游戏变速

java - 如果 equals 方法返回 true,如何在内存中分配相同的空间?

java - 具有良好性能的多重映射

java - 收到错误 "java.lang.IllegalStateException: Can print only from an activity"?

java - 带虚拟键盘的 Android onKey