在java中创建一个节省空间的通用对象

时间:2014-07-20 20:15:00

标签: java data-structures

我试图创建一个同时尽可能节省空间的对象,但也可以一般地工作,并且我遇到了一个重大问题。我想做的一个优化是从键中删除包装器(其中可以有任意数量的任意类型)。但我遇到了Java中泛型的本质问题。

似乎要使函数通用,它必须接受需要包装类的对象。如果我可以动态创建基本类型数组,那么解决方法就是。有谁知道我怎么能做到这一点?

1 个答案:

答案 0 :(得分:2)

首先,我怀疑你的意图会在存储方面做出任何可衡量的改进,但要回答这个问题......

我假设您的问题可以概括为"如果传递了包装器对象,我如何将它们存储为基元数组?",并暗示不允许null个对象。 / p>

您可以使用JDK中的库方法动态创建基本数组。您还没有显示任何代码,因此请根据需要进行修改:

这是一个简单的方法:

public static int[] unwrap(Integer... integers) {
    int[] array = new int[integers.length];
    for (int i = 0; i < integers.length; i++) {
        array[i] = integers[i]; // auto-unboxing
    }
    return array;
}

您可能只是为不同的包装器类型重载构造函数或工厂方法。

这是一个如何动态创建基本数组的更一般的例子:

public static int[] unwrap(Integer... integers) {
    int[] array = (int[]) Array.newInstance(int.class, integers.length);
    for (int i = 0; i < integers.length; i++) {
        array[i] = integers[i].intValue();
    }
    return array;
}

你可以为你的其他包装器类调整这个模式,例如通过存储在一个包装类使用哪个原始类(例如Integer.class --> int.class这里)的地图中,但是当涉及到正确的时候问题变得更加棘手来自包装器的值,例如,知道为Integer.intValue()调用int,为Long.longValue()调用long

但是,你可以反思性地解决这个问题:

private static Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>() {{
    put(Integer.class, int.class);
    put(Long.class, long.class);
    put(Float.class, float.class);
    put(Double.class, double.class);
    put(Character.class, char.class);
    put(Short.class, short.class);
    put(Byte.class, byte.class);
    put(Boolean.class, boolean.class);
}};

public static <T> Object unwrap(T first, T... rest) throws Exception {
    Class<?> outputType = map.get(first.getClass());
    if (outputType == null) {
        throw new UnsupportedOperationException();
    }
    Object array = Array.newInstance(outputType, rest.length + 1);
    Method getter = first.getClass().getMethod(outputType.getSimpleName() + "Value");
    for (int i = 0; i < rest.length + 1; i++) {
        T target = i == 0 ? first : rest[i - 1];
        Array.set(array, i, getter.invoke(target));
    }
    return array;
}

剩下的问题是原始数组Object[]的实例,所以你不能将返回类型声明为数组(没有常见的类型)对于原始数组)。

尽管如此,你可以保存你的数组对象,然后使用类似的方法进行查询,然后再调用包装器,除非你调用包装类的构造函数并从数组中传递一个元素,通过{{1 }}