Dodaj obiekt do ArrayList pod określonym indeksem

142

Myślę, że to dość proste pytanie, ale nie mogę wymyślić, jak to zrobić poprawnie.

Mam pustego arraylistę:

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

Mam kilka obiektów, które chcę dodać, a każdy z nich musi znajdować się w określonej pozycji. Konieczne jest jednak, aby można je było dodawać w każdej możliwej kolejności. Kiedy próbuję tego, nie działa i otrzymuję IndexOutOfBoundsException:

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

Co Próbowałem wypełnia ArrayListprzy nullczym robi to powyżej. Działa, ale uważam, że to okropne rozwiązanie. Czy jest inny sposób, aby to zrobić?

J. Maes
źródło
7
Otrzymujesz wyjątek IndexOutOfBoundsException, ponieważ lista jest pusta i nie możesz uzyskać dostępu do pozycji listy, która nie istnieje ...
Vic
1
Czy istnieje sposób na utworzenie tej pozycji bez wypełniania listy obiektami o wartości null? Wydaje mi się, że to naprawdę dziwne rozwiązanie.
J. Maes
1
Nie sądzę ... Jeśli chcesz dodać obiekty w losowej kolejności, musiałbyś poszukać innego sposobu zrobienia tego .. Na przykład z typową tablicą: „Obiekt []” i wtedy nie powinieneś nie trzeba go wypełniać, po prostu zainicjuj
Vic
1
@Maethortje, to naprawdę nie jest dziwny problem. Poszukaj rzadkich list, reference.wolfram.com/mathematica/tutorial/… wydaje się dobrym artykułem. Jednak w Javie mapa z indeksem jako kluczem może być najłatwiejszym podejściem.
Nędzna zmienna
2
@Pan Nawet jeśli zadeklarujesz rozmiar .. Po prostu nie inicjalizuje listy, ale deklaruje, ile miejsca chcesz zarezerwować w pamięci .. Jak widzę, lista jest tablicą elementów, która również ma wskaźnik do następny element. Jeśli spróbujesz dodać element na trzeciej pozycji, gdy drugi jest pusty (lub zerowy), nie masz wskaźnika, który pomógłby ci wiedzieć, że jest to trzeci element ..: 1-> 2-> 3 jest OK, ale 1- > * -> 3 tutaj masz problem ...
Vic

Odpowiedzi:

209

Możesz to zrobić w ten sposób:

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

Po dodaniu object2 do pozycji 2 przesunie on object3 na pozycję 3.

Jeśli chcesz, aby obiekt3 był na pozycji3 przez cały czas, sugerowałbym użycie HashMap z pozycją jako kluczem i obiektem jako wartością.

superM
źródło
3
Haszmapa rzeczywiście byłaby w stanie rozwiązać ten problem. Myślę, że wybiorę to, ponieważ nie wydaje mi się, żebym mógł dodać coś w lokalizacji 3, gdy nie ma obiektu w lokalizacji 2.
J. Maes
krótkie, ale większość odpowiedzi. Inni są po prostu na złej drodze
Shabbir Dhangot
Konstruktywna logika!
Arsal Imam
31

Możesz użyć tablicy obiektów i przekonwertować ją na 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 będzie wynosić- [1, null, 2, 3, null, null, null, 7, null, null]

user3484940
źródło
2
Wadą jest to, że musisz wcześniej znać rozmiar.
Daniel Hári,
17

Jeśli tak jest, to dlaczego nie rozważyć użycia zwykłej tablicy, zainicjuj pojemność i umieść obiekty w żądanym indeksie.

Object[] list = new Object[10];

list[0] = object1;
list[2] = object3;
list[1] = object2;
medopal
źródło
Inicjalizujesz pojemność, ale nie rozmiar „ArrayList”. Rozmiar jest definiowany jako liczba elementów, a gdy indeks jest> rozmiar, pojawia się wyjątek ...
Vic
@Vic, na początku źle odczytałem pytanie, ale dzięki za wskazówkę.
medopal
Zainicjowałem pojemność na 10, ale nadal otrzymuję IndexOutOfBoundsExceptopn podczas dodawania obiektu. To samo dotyczy zmiany pojemności przy użyciu funkcji sureCapacity. Jedyne, co działa, to wypełnienie w tej chwili null ...
J. Maes
@Maethortje Poszukaj różnicy między „rozmiarem” a „pojemnością” ... Wyjątek występuje, gdy indeks jest> rozmiar, a nie gdy jest> pojemność .....
Vic
Jak wspomnieli chłopcy, dodajesz obiekt o indeksie 3, podczas gdy rozmiar listy nadal wynosi 1. To niemożliwe. Dodawanie w określonym indeksie jest dozwolone, o ile indeks ten znajduje się w granicach listy, na przykład jeśli twoja lista zawiera 3 obiekty, nie możesz dodać obiektu o indeksie 100.
medopal
14

Możesz również zastąpić ArrayList, aby wstawić wartości null między rozmiarem a elementem, który chcesz dodać.

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);
    }
}

Następnie możesz dodać w dowolnym miejscu ArrayList. Na przykład ta główna metoda:

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));
    }
}   

daje taki wynik z konsoli:

0: zero

1 jeden

2: dwa

3: brak

4: brak

5: pięć

EngineerWithJava54321
źródło
9

Zwracam uwagę na ArrayList.adddokumentację , która mówi, że rzuca IndexOutOfBoundsException- jeśli indeks jest poza zakresem ( index < 0 || index > size())

Sprawdź size()swoją listę, zanim zadzwoniszlist.add(1, object1)

Nędzna zmienna
źródło
Masz rację @Hemal, @Maethortje Dlaczego nie sprawdzasz rozmiaru listy przed dodaniem elementu do listy? sprawdź, czy pozycja, którą próbujesz dodać jest mniejsza niż rozmiar listy, jeśli nie, możesz po prostu zrobić normalnąlist.add("element");
Rakesh
1
Jak rozumiem, „problemem” jest dodanie elementu na pozycji 3, nawet jeśli nie ma elementu na pozycji 2…
Vic
@Vis to rzadka lista - zobacz mój komentarz do pytania.
Nędzna zmienna
5

Musisz wypełnić puste indeksy wartościami null.

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

arraylist.add(position, object);
Miika Pakarinen
źródło
2
@Maethortje 

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

podczas próby dodania elementu na określonej pozycji otrzymałeś IndexOutOfBound, więc lista powinna zawierać elementy na swoich pozycjach.

Spróbuj śledzić

/*
  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

*/
Sankalp
źródło
Rozumiem problem, który powoduje mój błąd. Wygląda na to, że muszę dodać obiekty do kolejnych pozycji, zanim będę mógł dodać obiekt do tej pozycji. W momencie dodawania nie pozbywam się wszystkich obiektów, które chcę dodać. Czy uważasz, że dodawanie obiektów zerowych to właściwe rozwiązanie?
J. Maes
@Maethortje To nie będzie sprawiedliwe, bo to tylko hack :)
Sankalp
musisz usunąć przykładowe cudzysłowy kodu z pierwszego akapitu.
Jalal Sordo
2

A co z tą małą whilepętlą jako rozwiązaniem?

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)
Stewart
źródło
2

To jest możliwe rozwiązanie:

list.add(list.size(), new Object());
Darius
źródło
1

Myślę, że rozwiązanie od Medopal jest tym, czego szukasz.

Ale innym alternatywnym rozwiązaniem jest użycie HashMap i użycie klucza (Integer) do przechowywania pozycji.

W ten sposób nie będziesz musiał początkowo wypełniać go wartościami zerowymi itp., Po prostu przyklejaj pozycję i obiekt na mapie, gdy idziesz. Możesz napisać kilka wierszy na końcu, aby przekonwertować je na listę, jeśli potrzebujesz tego w ten sposób.

Ashkan Aryan
źródło
Czy TreeMap nie jest lepsza od zamówienia według kluczy?
Daniel Hári,
1

Załóżmy, że chcesz dodać element na pozycji, a wtedy rozmiar listy musi być większy niż pozycja.

add(2, item): ta składnia oznacza, przenieś stary element na pozycję 2 do następnego indeksu i dodaj element na drugiej pozycji.

Jeśli nie ma elementu na drugiej pozycji, to nie zadziała, zgłosi wyjątek.

To znaczy, jeśli chcesz coś dodaćposition 2,

Twój rozmiar listy musi wynosić co najmniej, (2 + 1) =3,aby pozycje były dostępne pod adresem0,1,2 Position.

w ten sposób zapewniony jest bezpieczny dostęp do pozycji 2 i nie byłoby wyjątku.

Shamsul Arefin Sajib
źródło
2
Właśnie przechodzę obok, kiedy powiadomiłem Cię o odpowiedzi ... właściwie indeks musi być mniejszy lub równy rzeczywistej długości listy w momencie wstawiania nowej pozycji. przykład: rozmiar listy to 2: dodanie indeksu 2 zadziała. dodanie indeksu 3 spowoduje zgłoszenie wyjątku. (Został przetestowany)
Houssem Chlegou
0

Jeśli korzystasz z wersji Java w systemie Android, mogę zasugerować użycie SparseArray . Jest to bardziej wydajne pod względem pamięci mapowanie liczb całkowitych na obiekty i łatwiejsze do iteracji niż mapa

AllDayAmazing
źródło
0

Trochę późno, ale mam nadzieję, że nadal komuś się przyda.

2 kroki, aby dodać elementy do określonej pozycji w pliku ArrayList

  1. add null elementy do określonego indeksu w pliku ArrayList
  2. Następnie setpozycje w razie potrzeby.

        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);

W ten sposób nie masz zbędnych elementów w ArrayListnp. Gdybyś miał dodać elementy takie jak,

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

Nie spowodowałoby to zastąpienia istniejących elementów w tej pozycji, po prostu przesunięcia istniejących elementów w prawo o jeden - więc masz ArrayList z dwukrotnie większą liczbą wskazań.

Zain
źródło
0

Należy ustawić zamiast dodawać, aby zastąpić istniejącą wartość w indeksie.

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

Lista będzie zawierać [obiekt1, obiekt2]

Saurabh
źródło