Как получить емкость ArrayList в Java?

Другая версия C # с ленивым поколением комбинационных индексов. Эта версия поддерживает единый массив индексов для определения сопоставления между списком всех значений и значениями для текущей комбинации, т. Е. Постоянно использует дополнительное пространство O (k) в течение всего времени выполнения. Код генерирует отдельные комбинации, включая первый, в O (k) времени.

public static IEnumerable<T[]> Combinations<T>(this T[] values, int k)
{
    if (k < 0 || values.Length < k)
        yield break; // invalid parameters, no combinations possible

    // generate the initial combination indices
    var combIndices = new int[k];
    for (var i = 0; i < k; i++)
    {
        combIndices[i] = i;
    }

    while (true)
    {
        // return next combination
        var combination = new T[k];
        for (var i = 0; i < k; i++)
        {
            combination[i] = values[combIndices[i]];
        }
        yield return combination;

        // find first index to update
        var indexToUpdate = k - 1;
        while (indexToUpdate >= 0 && combIndices[indexToUpdate] >= values.Length - k + indexToUpdate)
        {
            indexToUpdate--;
        }

        if (indexToUpdate < 0)
            yield break; // done

        // update combination indices
        for (var combIndex = combIndices[indexToUpdate] + 1; indexToUpdate < k; indexToUpdate++, combIndex++)
        {
            combIndices[indexToUpdate] = combIndex;
        }
    }
}

Код теста:

foreach (var combination in new[] {'a', 'b', 'c', 'd', 'e'}.Combinations(3))
{
    System.Console.WriteLine(String.Join(" ", combination));
}

Выход:

a b c
a b d
a b e
a c d
a c e
a d e
b c d
b c e
b d e
c d e
16
задан Guido 23 March 2010 в 08:07
поделиться

6 ответов

Я не думаю, что это возможно. Какой у вас вариант использования? Я считаю, что C # ArrayLists имеет свойство .capacity, но класс Java ArrayList не предоставляет эту информацию.

У вас есть конструктор, который принимает начальный аргумент емкости, и у вас есть метод sureCapacity (), который вы могли бы использовать для уменьшения количества постепенного перераспределения.

У вас также есть метод trimToSize (), который вы можете использовать, если действительно беспокоитесь об использовании памяти.

16
ответ дан Mark B 23 March 2010 в 08:07
поделиться

Не помню, было ли это, но вы могли бы сделать это самостоятельно, посмотрев на исходный код ArrayList. Разработчики Java должны использовать преимущества исходного кода, поставляемого в комплекте с SDK.

0
ответ дан instcode 23 March 2010 в 08:07
поделиться

Емкость по умолчанию ArrayList равна 10. Как только максимальный размер будет достигнут, новая емкость будет:

новая емкость = (текущая емкость * 3/2) +1.

0
ответ дан Avinash Kumar 23 March 2010 в 08:07
поделиться

Я только что проверил документацию sun по классу ArrayList , и единственный метод, который я видел, связанный с емкостью, был sureCapacity ( int minCapacity), что не совсем то, что вам нужно. Удачи!

0
ответ дан 30 November 2019 в 08:03
поделиться

Вы можете получить это отражение:

public abstract class ArrayListHelper {

    static final Field field;
    static {
        try {
            field = ArrayList.class.getDeclaredField("elementData");
            field.setAccessible(true);
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    @SuppressWarnings("unchecked")
    public static <E> int getArrayListCapacity(ArrayList<E> arrayList) {
        try {
            final E[] elementData = (E[]) field.get(arrayList);
            return elementData.length;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}
9
ответ дан 30 November 2019 в 08:03
поделиться

Посмотрев на спецификацию ArrayList, я не вижу метода, который предоставляет эту информацию.

Тем не менее, метод ensureCapacity кажется шагом в правильном направлении (предупреждение: он не гарантирует правильного ответа): При вызове он гарантирует, что емкость не меньше указанного аргумента. Таким образом, если реализация ArrayList использует этот метод для обеспечения емкости (в отличие от вызова какого-либо частного метода/манипулирования соответствующими полями напрямую), вы можете получить текущую емкость, переопределив этот метод. Вам также необходимо переопределить trimToSize() аналогичным образом.

Конечно, это решение не очень переносимо, поскольку другая реализация ArrayList (на JVM другого производителя) может делать все по-другому.

Вот как должен выглядеть код

public class CapacityTrackingArrayList<T> extends ArrayList<T> {

   // declare a constructor for each ArrayList constructor ...


   // Now, capacity tracking stuff:
   private int currentCapacity = 10;

   public int getCapacity() { return currentCapacity; }

   public void ensureCapacity(int arg) {
     currentCapacity = arg;
     super.ensureCapacity(arg);
   }

   public void trimToSize() { currentCapacity = size(); super.trimToSize(); }

}
2
ответ дан 30 November 2019 в 08:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: