Эффективно построить большой массив с методамиJAVA

Программисты JAVA общаются здесь
Anonymous
Эффективно построить большой массив с методами

Сообщение Anonymous »

Мне необходимо построить метод-индле с помощью Signature (InternalContext)-> Object [] из списка каждый с подписью (InternalContext)-> Object .
Если список маленький Object[]
var handle = MethodHandles.identity(Object[].class);
// (Object,Object...Object) -> Object[]
handle = handle.asCollector(Object[].class, elements.size());
// (InternalContext,InternalContext..InternalContext) -> Object[]
handle = MethodHandles.filterArguments(handle, 0, elements.toArray(new MethodHandle[0]));
// (InternalContext) -> Object[]
handle = MethodHandles.permuteArguments(
handle, methodType(Object[].class, InternalContext.class), new int[elements.size()]);
return handle;
}
[/code]
Однако, если список больше, Ascollector () вызов потерпит неудачу, так как результирующая ручка будет иметь слишком много параметров.
Поэтому я попробовал что -то подобное:

Код: Выделить всё

  private static final int MAX_ARITY = 255;

static MethodHandle buildLargeArrayNaive(List elementFactories) {
if (elementFactories.size() < MAX_ARITY) {
return makeArrayUsingCollector(elementFactories);
}
var setter = MethodHandles.arrayElementSetter(Object[].class);
// (Object[], InternalContext) -> void
MethodHandle handle = null;
for (int i = 0; i < elementFactories.size(); i++) {
// (Object[], InternalContext) -> void
var setElement =
MethodHandles.filterArguments(
MethodHandles.insertArguments(setter, 1, i), 1, elementFactories.get(i));
if (handle == null) {
handle = setElement;
} else {
handle = MethodHandles.foldArguments(setElement, handle);
}
}

// (Object[], InternalContext) -> Object[]
handle =
MethodHandles.foldArguments(
MethodHandles.dropArguments(
MethodHandles.identity(Object[].class), 1, InternalContext.class),
handle);
return MethodHandles.foldArguments(
handle,
MethodHandles.insertArguments(
MethodHandles.arrayConstructor(Object[].class), 0, elementFactories.size()));
}
, который в основном строит массив явно, а затем устанавливает каждый элемент, объединяющий все с помощью Foldarguments
Это работает, но полученный метод производит Stackoverflower при конструировании больших массивов (скажем, 100K Elements). Из документов on foldarguments это имеет смысл, поскольку каждый вызов устанавливает структуру «хвостового вызова».

Код: Выделить всё

static makeArray(InternalContext ctx) {
var a = new Object[
Я обнаружил, что могу решить это с помощью рекурсии < /p>
 static MethodHandle buildLargeArrayRecursive(List elementFactories) {
// (Object[], InternalContext) -> void
var handle = doBuildLargeArrayRecursive(0, elementFactories);
// (Object[], InternalContext) -> Object[]
handle =
MethodHandles.foldArguments(
MethodHandles.dropArguments(
MethodHandles.identity(Object[].class), 1, InternalContext.class),
handle);
;
return MethodHandles.foldArguments(
handle,
MethodHandles.insertArguments(
MethodHandles.arrayConstructor(Object[].class), 0, elementFactories.size()));
}

static final MethodHandle ARRAY_SETTER = MethodHandles.arrayElementSetter(Object[].class);

static MethodHandle doBuildLargeArrayRecursive(int offset, List elementFactories) {
int size = elementFactories.size();
if (size == 0) {
return MethodHandles.empty(methodType(void.class, Object[].class, InternalContext.class));
}
if (size == 1) {
return MethodHandles.filterArguments(
MethodHandles.insertArguments(ARRAY_SETTER, 1, offset), 1, elementFactories.get(0));
}
int half = size / 2;
var left = elementFactories.subList(0, half);
var right = elementFactories.subList(half, size);
return MethodHandles.foldArguments(
doBuildLargeArrayRecursive(offset + half, right), doBuildLargeArrayRecursive(offset, left));
}
< /code>
, который, по -видимому, масштабируется как минимум до 100 тыс. Элементов.  Но ясно, что это будет потреблять пространство стека O (logn). Это, вероятно, хорошо, но это также много вызовов методов ... < /p>
Несколько вещей произошли, уставившись на это: < /p>
[list]
[*]  Должен ли я создавать вспомогательные методы для обработки более базовых случаев?  например static void set4 (object [], int смещение, объект O1 ... объект O3) {...} 
может помочь уменьшить рекурсию? Или я должен просто полагаться на виртуальную машину, чтобы сделать это через Inlining? /> Было бы лучше построить небольшие массивы и исправлять их вместе с помощью system.arraycopy ?

[/list]

Подробнее здесь: https://stackoverflow.com/questions/795 ... hodhandles

Вернуться в «JAVA»