Добавить объект в ArrayList по указанному индексу

142

Я думаю, что это довольно простой вопрос, но я не могу понять, как это сделать правильно.

У меня пустой массив:

ArrayList<object> list = new ArrayList<object>();

У меня есть несколько объектов, которые я хочу добавить, и каждый объект должен находиться в определенной позиции. Однако необходимо, чтобы их можно было добавлять в любом возможном порядке. Когда я пытаюсь это сделать, это не работает, и я получаю IndexOutOfBoundsException:

list.add(1, object1)
list.add(3, object3)
list.add(2, object2)

То , что я пытался это заполнение ArrayListс , nullа затем делать выше. Это работает, но я считаю это ужасным решением. Есть другой способ сделать это?

Дж. Маес
источник
7
Вы получаете исключение IndexOutOfBoundsException, потому что список пуст, и вы не можете получить доступ к позиции в списке, которой не существует ...
Вик,
1
Есть ли способ создать эту позицию без заполнения списка нулевыми объектами? Мне кажется, что это действительно странное решение.
J. Maes
1
Я так не думаю ... Если вам нужно добавить объекты в случайном порядке, вам придется искать другой способ сделать это .. Например, с типичным массивом: 'Object []', а затем вы не должны не нужно его заполнять, просто инициализируйте
Вик
1
@Maethortje, это не такая уж странная проблема. Посмотрите разреженные списки, reference.wolfram.com/mathematica/tutorial/… кажется хорошей статьей. Однако в Java самым простым подходом может быть карта с индексом в качестве ключа.
Miserable Variable
2
@Pan Даже если вы объявляете размер ... Он просто не инициализирует список, а объявляет, сколько места вы хотите зарезервировать в памяти .. Насколько я понимаю, список - это массив элементов, который также имеет указатель на следующий элемент. Если вы попытаетесь добавить элемент в третью позицию, когда у вас есть второй пустой (или нулевой), у вас нет указателя, который поможет вам узнать, что это третий элемент ..: 1-> 2-> 3 в порядке, но 1- > * -> 3 вот у вас проблема ...
Вик

Ответы:

211

Сделать это можно так:

list.add(1, object1)
list.add(2, object3)
list.add(2, object2)

После того, как вы добавите объект2 в позицию 2, он переместит объект3 в позицию 3.

Если вы хотите, чтобы объект 3 все время находился в позиции 3, я бы посоветовал вам использовать HashMap с позицией в качестве ключа и объектом в качестве значения.

superM
источник
3
Хэш-карта действительно могла бы решить эту проблему. Думаю, я выберу это, поскольку не похоже, что я могу добавить что-то в местоположении 3, когда в местоположении 2 нет объекта
J. Maes
краткий, но самый ответ. Другие просто ошибаются
Шабир Дхангот
Конструктивная логика!
Arsal Imam
33

Вы можете использовать массив объектов и преобразовать его в ArrayList-

Object[] array= new Object[10];
array[0]="1";
array[3]= "3";
array[2]="2";
array[7]="7";

List<Object> list= Arrays.asList(array);

ArrayList будет- [1, null, 2, 3, null, null, null, 7, null, null]

user3484940
источник
2
Один недостаток - нужно заранее знать размер.
Daniel Hári
17

Если это так, то почему бы вам не рассмотреть возможность использования обычного массива, инициализировать емкость и разместить объекты по желаемому индексу.

Object[] list = new Object[10];

list[0] = object1;
list[2] = object3;
list[1] = object2;
медопал
источник
Вы инициализируете емкость, но не размер «ArrayList». Размер определяется как количество элементов, и когда индекс> size, возникает исключение ...
Вик,
@Vic, я сначала неправильно понял вопрос, но спасибо за подсказку.
medopal
Я инициализировал емкость равной 10, но при добавлении объекта я все еще получаю IndexOutOfBoundsExceptopn. То же самое с изменением емкости с помощью sureCapacity. Единственное, что работает, - это заполнение нулями на данный момент ...
J. Maes
@Maethortje Ищите разницу между "размером" и "емкостью" ... Исключение возникает, когда индекс> размера, а не когда он> емкости .....
Вик
Как уже упоминалось, вы добавляете объект с индексом 3, а размер списка по-прежнему равен 1. Это невозможно. Добавление по определенному индексу разрешено, пока этот индекс находится внутри границ списка, например, если в вашем списке 3 объекта, вы не можете добавить объект с индексом 100.
medopal
14

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

import java.util.ArrayList;


public class ArrayListAnySize<E> extends ArrayList<E>{
    @Override
    public void add(int index, E element){
        if(index >= 0 && index <= size()){
            super.add(index, element);
            return;
        }
        int insertNulls = index - size();
        for(int i = 0; i < insertNulls; i++){
            super.add(null);
        }
        super.add(element);
    }
}

Затем вы можете добавить в любой момент в ArrayList. Например, этот основной метод:

public static void main(String[] args){
    ArrayListAnySize<String> a = new ArrayListAnySize<>();
    a.add("zero");
    a.add("one");
    a.add("two");
    a.add(5,"five");
    for(int i = 0; i < a.size(); i++){
        System.out.println(i+": "+a.get(i));
    }
}   

дает следующий результат из консоли:

0: ноль

1: один

2: два

3: ноль

4: ноль

5: пять

EngineerWithJava54321
источник
10

Обращаю ваше внимание на ArrayList.addдокументацию , в которой написано, что выкидывает IndexOutOfBoundsException- если индекс вне допустимого диапазона ( index < 0 || index > size())

Проверьте size()свой список, прежде чем звонитьlist.add(1, object1)

Жалкая переменная
источник
Вы правы @Hemal, @Maethortje Почему бы вам не проверить размер списка перед тем, как добавить элемент в список? проверьте, меньше ли позиция, которую вы пытаетесь добавить, чем размер списка, если нет, тогда вы можете просто сделать как обычноlist.add("element");
Ракеш
1
Насколько я понимаю, «проблема» состоит в том, чтобы добавить элемент в позицию 3, даже если нет элемента в позиции 2 ...
Vic
@Vis это скудный список - см. Мой комментарий к вопросу.
Miserable Variable
5

Вам нужно заполнить пустые индексы нулями.

while (arraylist.size() < position)
{
     arraylist.add(null);
}

arraylist.add(position, object);
Миика Пакаринен
источник
2
@Maethortje 

The problem here is java creates an empty list when you called new ArrayList and 

при попытке добавить элемент в указанную позицию вы получили IndexOutOfBound, поэтому в списке должны быть некоторые элементы на их позиции.

Пожалуйста, попробуйте следовать

/*
  Add an element to specified index of Java ArrayList Example
  This Java Example shows how to add an element at specified index of java
  ArrayList object using add method.
*/

import java.util.ArrayList;

public class AddElementToSpecifiedIndexArrayListExample {

  public static void main(String[] args) {
    //create an ArrayList object
    ArrayList arrayList = new ArrayList();

    //Add elements to Arraylist
    arrayList.add("1");
    arrayList.add("2");
    arrayList.add("3");

    /*
      To add an element at the specified index of ArrayList use
      void add(int index, Object obj) method.
      This method inserts the specified element at the specified index in the
      ArrayList.  
    */
    arrayList.add(1,"INSERTED ELEMENT");

    /*
      Please note that add method DOES NOT overwrites the element previously
      at the specified index in the list. It shifts the elements to right side
      and increasing the list size by 1.
    */

    System.out.println("ArrayList contains...");
    //display elements of ArrayList
    for(int index=0; index < arrayList.size(); index++)
      System.out.println(arrayList.get(index));

  }
}

/*
Output would be
ArrayList contains...
1
INSERTED ELEMENT
2
3

*/
Санкальп
источник
Я понимаю проблему, которая вызывает мою ошибку. Похоже, мне нужно добавить объекты в последующие позиции, прежде чем я смогу добавить объект в эту позицию. В момент добавления я не удаляю все объекты, которые хочу добавить. Как вы думаете, добавление нулевых объектов - правильное решение?
J. Maes
@Maethortje: Это будет несправедливо, потому что это просто взлом :)
Sankalp
вам нужно удалить кавычки образца кода из первого абзаца.
Джалал Сордо
2

Как насчет этой маленькой whileпетли как решения?

private ArrayList<Object> list = new ArrayList<Object>();

private void addObject(int i, Object object) {
    while(list.size() < i) {
        list.add(list.size(), null);
    }
    list.add(i, object);
}
....

addObject(1, object1)
addObject(3, object3)
addObject(2, object2)
Стюарт
источник
2

Это возможное решение:

list.add(list.size(), new Object());
Дариус
источник
1

Я думаю, что решение от medopal - это то, что вы ищете.

Но еще одно альтернативное решение - использовать HashMap и использовать ключ (Integer) для хранения позиций.

Таким образом, вам не нужно будет изначально заполнять его нулями и т. Д., Просто вставьте позицию и объект на карту по мере продвижения. Вы можете написать пару строк в конце, чтобы преобразовать его в список, если он вам так нужен.

Ашкан Ариан
источник
Разве TreeMap не лучше, так как заказывается по ключам?
Daniel Hári
1

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

add(2, item): этот синтаксис означает, что переместите старый элемент с позиции 2 на следующий индекс и добавьте элемент во вторую позицию.

Если во 2-й позиции нет элемента, это не сработает, это вызовет исключение.

Это означает, что если вы хотите что-то добавить вposition 2,

размер вашего списка должен быть не меньше, (2 + 1) =3,чтобы элементы были доступны по адресу0,1,2 Position.

таким образом обеспечивается безопасный доступ к позиции 2 и не будет никаких исключений.

Шамсул Арефин Саджиб
источник
2
Я просто прохожу мимо, когда я уведомил ваш ответ ... на самом деле, индекс должен быть меньше или равен реальной длине списка в момент, когда мы вставляем новый элемент. Пример: размер списка равен 2: добавление индекса 2 будет работать. добавление в индекс 3 вызовет исключение. (Это было проверено)
Houssem Chlegou
0

Если вы используете версию Java для Android, могу ли я предложить SparseArray . Это более эффективное сопоставление целых чисел с объектами с точки зрения памяти, и его проще перебирать, чем Map

AllDayAmazing
источник
0

Немного поздно, но, надеюсь, может быть кому-то полезен.

2 шага для добавления элементов в определенную позицию в ArrayList

  1. add нулевые элементы для определенного индекса в ArrayList
  2. Затем setпозиции по мере необходимости.

        list = new ArrayList();//Initialise the ArrayList
    for (Integer i = 0; i < mItems.size(); i++) {
        list.add(i, null); //"Add" all positions to null
    }
       // "Set" Items
        list.set(position, SomeObject);
    

Таким образом, у вас не будет лишних элементов, ArrayListт.е. если бы вы добавили такие элементы, как,

list = new ArrayList(mItems.size());    
list.add(position, SomeObject);

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

Zain
источник
0

Вы должны установить вместо добавления, чтобы заменить существующее значение в индексе.

list.add(1, object1)
list.add(2, object3)
list.set(2, object2)

Список будет содержать [объект1, объект2]

Саураб
источник