Нужен совет о том, как распечатать оставшуюся емкость ArrayList - PullRequest
5 голосов
/ 10 июля 2020

Я пытаюсь выяснить, как я могу получить вывод оставшихся слотов, доступных при удалении 1 объекта.

    ListOfMembers = new ArrayList<>(100); which caps my list at 100.

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

    public boolean DeleteMember() {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter the membership number: ");
        String pno = in. nextLine();
        for(int i=0;i<ListOfMembers.size();++i) {
            if(ListOfMembers.get(i).getMembershipNumber().equals(pno)) {
                ListOfMembers.remove(i);
                System.out.println("Space available: " +?????);
                return true;
            }
        }
                System.out.println("Numbership number does not exist");
        return false;
    }

Использование System.out.println("Space available: " +ListOfMembers.size()) предоставит количество записей, а я пытаюсь получить противоположное.

Ответы [ 4 ]

5 голосов
/ 10 июля 2020

Вы, кажется, неправильно понимаете, как работает arraylist.

new ArrayList<>(100) не закрывает список. 100 - это просто подсказка.

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

ArrayList работает «под капотом», имея массив, содержащий ваши элементы. Проблема в том, что java не позволяет массивам увеличиваться или уменьшаться. ArrayList решает эту проблему с помощью двух приемов:

  1. За счет внутреннего отслеживания длины ArrayList, ArrayList impl может использовать «слишком большой» массив.
  2. Если вы вы заполнили свой arrayylist таким образом, чтобы в нем было столько элементов, сколько «резервный массив большой», и вы добавляете еще один элемент, у arraylist проблема - резервный массив вне места. Затем ArrayList создаст новый массив большего размера, скопирует все элементы из старого массива, теперь добавит новый элемент (поскольку есть место; этот новый массив больше), а затем избавится от старого массива.

Единственное, что 100 делает в вашем конструкторе, - это подсказка: насколько большим должен быть изначально сделан резервный массив. Из коробки (всего new ArrayList<>()) вы получаете подсказку по умолчанию 10.

Попробуйте! запустите это:

List<String> list = new ArrayList<String>(100);
for (int i = 0; i < 200; i++) list.add("" + i);
System.out.println(list.size());

Этот код будет нормально компилироваться, работать нормально и печатать 200. Таким образом, доказывая, что «100» не имеет абсолютно ничего общего с ограничением размера этого списка.

Итак, как вы можете ограничить размер Arraylist?

Нет. Arraylist не может этого сделать. Вместо этого вы оборачиваете или расширяете. Для серьезных кодовых баз я настоятельно рекомендую обертывать, но для простого упражнения расширение может сделать ваш код немного короче:

public class LimitedList<T> extends ArrayList<T> {
    private final int limit;

    public LimitedList(int limit) {
        this.limit = limit;
    }

    @Override public boolean add(T in) {
        if (size() >= limit) throw new IllegalStateException("List is full");
        super.add(in);
    }

    @Override public boolean addAll(Collection<T> in) {
        // left as an exercise for the reader
    }

    @Override public boolean addAll(int index, Collection<T> in) {
        // left as an exercise for the reader
    }

    @Override public boolean add(int idx, T in) {
        // left as an exercise for the reader
    }

    @Override public List<T> subList(int from, int to) {
        // this one gets complicated!
        // let's just not allow it.
        throw new UnsupportedOperationException();
    }

    public int available() {
        return limit - size();
    }
}

NB: Как видите, вы должны быть очень осторожны и переопределять каждый метод, который может увеличить список; вот почему создание нового типа, который вообще не расширяет ArrayList, а вместо этого имеет 1 поле типа ArrayList (и, конечно, 1 поле типа int для ограничения), может быть лучше: теперь вам явно нужно подумать о каждый список методов имеет, вместо того, чтобы молиться, вы покрыли все те, которые добавляют вещи.

*) ну, прагматично говоря, у вас не может быть более 2 ^ 31-1 элементов.

2 голосов
/ 10 июля 2020

Емкость - это внутренняя метрика c, которая используется для динамического увеличения доступного пространства, используемого ArrayList<>(). Обычно для пользователя не имеет значения, как это делается, поскольку это внутренняя проблема.

Однако возможность установки емкости позволяет пользователю указать значение, указывающее начальное содержимое, которое будет содержать список. Преимущество состоит в том, что он позволяет списку заполнять резервный массив без постоянной корректировки емкости, что приводит к большому копированию объектов.

Регулировка емкости

В любое время вы также можете увеличить емкость, используя метод ensureCapacity().

Уменьшите емкость

И вы также можете освободить неиспользованную емкость, используя метод trimToSize(). Это может освободить память в JVM .

Но ничто из вышеперечисленного не помешает вам добавить дополнительные записи в список. Они просто позволяют сделать оптимальный выбор, основываясь на априорном знании данных.

2 голосов
/ 10 июля 2020

Читая спецификацию List , говорится, что реализации просто не могут реализовать add; или откажитесь от добавления элементов в зависимости от типа или какого-либо свойства элемента ; но это не говорит о том, что список может отказаться от добавления элемента на основе текущего размера списка. Таким образом, ограничение размера нарушает заменяемость Лискова .

Вы можете определить LimitedSizeList implements Collection, но это не может быть истинной реализацией java.util.List.

Вы можете легко реализовать LimitedSizeList, расширив AbstractCollection:

class LimitedSizeList<E> extends AbstractCollection<E> {
  private final List<E> list = new ArrayList<>();
  private final int capacity;

  LimitedSizeList(int capacity) {
    this.capacity = capacity;
  }

  // Fill in the methods described in the Javadoc:
  @Override
  public Iterator<E> iterator() { return list.iterator(); }

  @Override
  public int size() { return list.size(); }

  @Override
  public boolean add(E element) {
    // Collection.add does allow you to throw an IllegalStateException
    // https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#add-E-
    if (remainingCapacity() <= 0) throw new IllegalStateException("Full");
    return list.add(element)
  }

  // You don't have to, but you might want to consider overriding
  // addAll, in order to make trying to add too-large a collection
  // failure atomic (that is, it fails to add any rather than some).

  // And then provide a method to report the free capacity:
  int remainingCapacity() {
    return capacity - size();
  }
}

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

Конечно, если вы действительно хотите, чтобы это было недействительным List (или вы можете гарантировать, что его не нужно будет рассматривать как универсальный List), вместо этого вы можете расширить AbstractList: методы, которые вам нужно реализовать, разные, но есть относительно немного, и они довольно простые. Однако нарушение контрактов - это хороший способ получить неожиданные ошибки в неожиданных местах вашего кода.

1 голос
/ 10 июля 2020

Вы можете использовать отражение для выполнения этой задачи, чтобы сначала получить емкость , а затем вычесть фактический размер

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("h");
        try {
            Field field = list.getClass().getDeclaredField("elementData");
            field.setAccessible(true);
            int cap = Array.getLength(field.get(list));
            System.out.println("The capacity: " + cap);
            System.out.println("The size: " + list.size());
            System.out.println("The remaining capacity: " + (cap - list.size()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

, вывод

The capacity: 10
The size: 6
The remaining capacity: 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...