• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wstawianie do listy elementów innej listy

Object Storage Arubacloud
0 głosów
249 wizyt
pytanie zadane 30 maja 2021 w Java przez cba Użytkownik (620 p.)

Witam, mam problem z tym jak umieścić elementy listy B do listy A przy pomocy iteratora a także iterując w tył usunąć elementy listy A i znowu wypisać zawartość.

Oto mój kod...

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListyZadDom
{
    public static void main(String args []){
        List<String> A= new ArrayList<String>();
        A.add("1");
        A.add("2");
        A.add("3");
        A.add("4");
        List<String> B= new ArrayList<String>();
        B.add("A");
        B.add("B");
        B.add("C");
        B.add("D");
        ListIterator<String> iterator = A.listIterator();

        while(iterator.hasNext()){
        iterator.next();
        A.add(B);
        }

        System.out.println(A);

        }
        }

 

1 odpowiedź

+2 głosów
odpowiedź 30 maja 2021 przez HaKIM Szeryf (87,590 p.)
edycja 30 maja 2021 przez HaKIM

Po pierwsze, czytaj i staraj się zrozumieć błędy zwracane przez program.
Po drugie, czytaj dokumentacje używanych przez Ciebie komponentów.

Metoda listIterator zwraca obiekt ListIterator typu elementu wywołującej jej listy - w tym przypadku String.

ListIterator<String>

Obiekt ListIterator zawiera następujące metody:

https://www.tutorialspoint.com/java/java_using_iterator.htm

Teraz, gdy zaznajomimy się z działaniem każdej z metod możemy wywnioskować, że będziemy potrzebować kolejno hasNextadd i next.

No więc tworzymy pętle:

while(iterator.hasNext()) {
    ...
}

Wewnątrz pętli chcemy dodać elementy listy "B".

Instrukcja, którą próbowałeś, A.add(B) nie zadziałała, gdyż A jest typu ArrayList a jej metoda add przyjmuje argumenty element typu String oraz opcjonalnie index typu Int podczas gdy próbujesz dodać element typu ArrayList<String> (patrz typ zmiennej B).

Gdybyś zrozumiał błąd, który program Ci zwrócił, wiedziałbyś o tym.

Będąc wzbogaconym o tę wiedzę, możemy przystąpić do solucji. 

Zacznijmy od mniej eleganckiej wersji:

...
ListIterator<String> bIterator = B.listIterator();

while(iterator.hasNext()) {
    while (bIterator.hasNext()) {
        iterator.add(bIterator.next());
    }
    
    iterator.next(); // Zalecam jednak wykonanie instrukcji "break" w tym przypadku. Output ten sam, natomiast program zyska na optymalizacji a iterator nadal jest w grze.
}

Wiemy, że B ma elementy tego samego typu co A, więc metoda A.add(elementB) zadziała. Stąd, jeżeli chcemy wykazać się fanatyzmem dla podejścia z użyciem iteratorów, tworzymy bIterator a następnie przypisujemy elementy bIterator do iterator (Sugerowałbym nazwy bIterator i aIterator, ale to inna sprawa).

Powyższy program zadziała.

Teraz czas na solucję bardziej elegancką, przy okazji podkreślającą, że znajomość dokumentacji obiektów z którymi pracujemy jest istotna.

Zapoznawszy się z dokumentacją obiektu ArrayList wiem, że zawiera ona metodę addAll((Collection(? Extends E) c). Znając typy listy A i B oraz wymagany typ parametru c metody addAll wiemy, że poniższy kod zadziała:

...
B.add("C");
B.add("D");

A.addAll(B);
System.out.println(A);

Link do dokumentacji: https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html

Z resztą zadań zostawiam Cię sam, jestem pewny, że uda Ci się rozwiązać resztę zadań, jeśli podejdziesz do tematu z chęcią zgłębienia pisanych przez siebie programów i używanych przez niego zasobów jak biblioteka java.

EDIT

Kolega Subtelny podsunął mi, że trafniejszym rozwiązaniem tego problemu jest program poniżej:

List<String> A = new ArrayList<>();
A.add("1");
A.add("2");
A.add("3");
A.add("4");

List<String> B = new ArrayList<>();
B.add("A");
B.add("B");
B.add("C");
B.add("D");

ListIterator<String> bListIterator = B.listIterator();
bListIterator.forEachRemaining(A::add);

System.out.println(Arrays.toString(A.toArray()));

Metoda forEachRemaining: https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html

Usunięcie elementów iteratora B z elementów listy A pozostawiam jako ćwiczenie, co powinno być prostsze z tym rozwiązaniem.

komentarz 31 maja 2021 przez cba Użytkownik (620 p.)
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListyZadDom
{
    public static void main(String[] args){
        List<String> A= new ArrayList<>();
        A.add("1");
        A.add("2");
        A.add("3");
        A.add("4");
        List<String> B= new ArrayList<>();
        B.add("A");
        B.add("B");
        B.add("C");
        B.add("D");
        ListIterator<String> aIterator = A.listIterator();

        ListIterator<String> bIterator = B.listIterator();
        int i=0 ,j=0;
        while(aIterator.hasNext()) {
            i++;
            if (i % 2 == 0) {
                aIterator.next();
                aIterator.add(bIterator.next());

            }
        }
        System.out.println(A);

        while (j<8)
        {
            aIterator.previous();
            j++;
            if(j%2==0)
            {
                aIterator.remove();

            }

        }
        System.out.println(A);
    }
}

Zrobiłem to w ten sposób bo miały być naprzemiennie dodawane elementy, jednak problem jest jeśli listy nie są tej samej długości. Próbowałem to jakoś rozwiązać if-ami ale nic nie chciało działać właściwie. Nie mam pomysłu jak można to zrobić. 

komentarz 31 maja 2021 przez HaKIM Szeryf (87,590 p.)
    val A: MutableList<String> = arrayListOf("1", "2")
    val B: MutableList<String> = arrayListOf("A", "B", "C", "D")

    val bListIterator: ListIterator<String> = B.listIterator()

    var position = 0
    while (bListIterator.hasNext()) {
        if (position > A.size) {
            A.add(bListIterator.next())
            continue
        }

        A.add(position, bListIterator.next())
        position += 2
    }

    println(A)

    while (bListIterator.hasPrevious()) {
        A.remove(bListIterator.previous())
    }

    println(A)

Program napisany w języku Kotlin/JVM, więc nie powinieneś mieć problemu ze zrozumieniem.

Myślę, że program jest zrozumiały oprócz pierwszego warunku w pierwszej pętli while - sprawdzam tam czy docelowa pozycja elementu B przekroczy wielkość tablicy A. Bez tego warunku mógłbyś spotkać się z IndexOutOfBounds exception.

Jeżeli masz pewność, że tablice A i B będą miały taką samą wielkość, możesz usunąć ten warunek.

Szczerze powiedziawszy, nie podoba mi się ten kod, głównie przez ifa sprawdzającego wielkość tablicy przeciwko docelowej pozycji - może ktoś znajdzie lepsze rozwiązanie.

Podobne pytania

0 głosów
1 odpowiedź 97 wizyt
pytanie zadane 11 listopada 2022 w Java przez ZiBi312 Nowicjusz (150 p.)
0 głosów
1 odpowiedź 1,314 wizyt
pytanie zadane 12 września 2016 w Java przez Patryk Rafał Bywalec (2,700 p.)

92,573 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...