Удаление связанного списка () и индекс не точен - PullRequest
0 голосов
/ 03 марта 2020

Я пытался удалить все кратные числа выбранного числа из связанного списка, как, например, удаление кратных 2:

[0, 12, 16, 0, 13, 9, 13, 17 , 5, 12, 1, 12, 5, 5, 1, 6, 14, 12, 14, 14] -> [13, 9, 13, 17, 5, 1, 5, 5, 1] ​​

Я написал этот код, чтобы создать связанный список из 20 случайных целых чисел, а затем, в зависимости от условия, удалить из него элементы.

import java.util.Scanner;
import java.util.*;

public class MyList {
    public static void main(String args[])
    {
        int entero = 0;
        Random random = new Random();
        LinkedList<Integer> objectList = new LinkedList<Integer>();
        Scanner scan = new Scanner(System.in);
        for(int i=0; i<20; i++){
            int randomInteger = random.nextInt(20);
            objectList.add(randomInteger);
        }
        System.out.print("Enter a number between 1 y 5: ");
        int intNumber = scan.nextInt();
        if(intNumber > 5 || intNumber < 1){
        }else{
            System.out.println("List : " + objectList);
            if(intNumber == 2){
                for(int j=0; objectList.size()>j; j++){
                    System.out.println("va " + objectList.get(j));
                    if (objectList.get(j) % 2 == 0) {
                        objectList.remove(objectList.get(j));;
                    }
                }
            }
        }
        System.out.println("Final List : " + objectList);
    }
}

Проблема в том, что он не будет удалять определенные элементы, даже если он должен (например, условие 14% 2 == 0 будет оценено как истинное, но число не будет удалено), поэтому результат заканчивается так:

из [0, 12, 16, 0, 13, 9, 13, 17, 5, 12, 1, 12, 5, 5, 1, 6, 14, 12, 14 , 14] -> к [0, 13, 9, 13, 17, 5, 1, 5, 5, 1, 12, 14, 14]

Почему это не удаляет все кратные 2 из список?

Ответы [ 5 ]

2 голосов
/ 03 марта 2020

Проблема заключается в том, что вы удаляете элементы из списка во время итерации по списку. Вот почему он ведет себя не так, как вы предполагаете.
Вы удаляете элементы списка, перебирая его. Так, например, после удаления элемента с индексом 0 следующая итерация будет указывать на objectList [1], который был objectList [2] до удаления objectList [0]. Это легко увидеть при отладке.

import java .util.Scanner; import java .util. *;

public class MyList {
    public static void main(String args[])
    {
        int entero = 0;
        Random random = new Random();
        LinkedList<Integer> objectList = new LinkedList<Integer>();
        LinkedList<Integer> removeObjectList = new LinkedList<Integer>();
        Scanner scan = new Scanner(System.in);
        for(int i=0; i<20; i++){
            int randomInteger = random.nextInt(20);
            objectList.add(randomInteger);
        }
        System.out.print("Enter a number between 1 y 5: ");
        int intNumber = scan.nextInt();
        if(intNumber > 5 || intNumber < 1){
        }else{
            System.out.println("List : " + objectList);
            if(intNumber == 2){
                for(int j=0; objectList.size()>j; j++){
                    System.out.println("va " + objectList.get(j));
                    if (objectList.get(j) % 2 == 0) {
//                        objectList.remove(objectList.get(j));// do not remove element from here.
                        removeObjectList.add(objectList.get(j));
                    }
                }
            }
        }

        LinkedList<Integer> finalList = new LinkedList<>();
        for(Integer num : objectList){
            if(removeObjectList.stream().noneMatch(it -> it.equals(num))){
                finalList.add(num);
            }
        }
        System.out.println("Final List : " + objectList);
    }

}

2 голосов
/ 03 марта 2020

Вы удаляете элементы списка, перебирая его. Так, например, после удаления элемента с индексом 0 следующая итерация будет указывать на objectList [1], который был objectList [2] до удаления objectList [0]. Вы можете легко увидеть это при отладке.

Таким образом, вы можете, например, создать список элементов для удаления, а затем использовать removeAll (toDelete).

Но, как по мне, лучший способ это использовать поток API.

objectList.stream().filter(o -> o%2!=0).collect(Collectors.toList())

вернет именно то, что вам нужно.

Обновление: я только что нашел, есть метод removeIf(Predicate<? super E> filter).

Так что вы можете просто использовать

l.removeIf(o -> o % 2 == 0);

Наслаждайся;)

1 голос
/ 03 марта 2020

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

Однако вы можете использовать метод iterator.remove () для решения вашей проблемы. В этом случае вы должны перебрать итератор. И код может быть следующим:

if(intNumber == 2){
        Iterator<Integer> iter = objectList.iterator(); 
        while (iter.hasNext()) { 
           if (iter.next() % 2 == 0) {
                iter.remove();;
           }
        } 
}

Это должно решить вашу проблему. Дайте мне знать, если вы не поняли какую-либо часть. Удачного кодирования!

0 голосов
/ 03 марта 2020

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

Если вы измените значение для l oop на отрицательное направление, ваш код будет работать:

for (int j = objectList.size () - 1; 0

Таким образом, окончательное решение может выглядеть следующим образом (Код с небольшими улучшениями):

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class MyList  {

    public static void main(String args[]) {
        int entero = 0;
        Random random = new Random();
        ArrayList<Integer> integerList = new ArrayList<Integer>();
        Scanner scan = new Scanner(System.in);
        for (int i = 0; i < 20; i++) {
            int randomInteger = random.nextInt(20);
            integerList.add(randomInteger);
        }
        System.out.print("Enter a number between 1 y 5: ");
        int intNumber = scan.nextInt();
        while (intNumber < 1 || 5 < intNumber) {
            System.out.print(
                    "Youre entered number does not match the asked set, please enter number with matches mathematical set {x∈ℕ|1<x<5}");
            intNumber = scan.nextInt();
        }
        System.out.println("Random List : " + integerList);
        for (int j = integerList.size() - 1; 0 < j; j--) {
            if (integerList.get(j) % intNumber == 0) {
                integerList.remove(integerList.get(j));
            }
        }
        System.out.println("Final List, filtered out \"" + intNumber + "\" and its multiples: " + integerList);
    }
}
0 голосов
/ 03 марта 2020

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

Enter a number between 1 y 5: 2
List : [0, 12, 16, 0, 13, 17, 5, 12, 1, 12, 1, 12, 5, 5, 1, 6, 14, 12, 14, 14]
objectList.get(j)%2 = 0
Deleting 0
List : [12, 16, 0, 13, 17, 5, 12, 1, 12, 1, 12, 5, 5, 1, 6, 14, 12, 14, 14]
objectList.get(j)%2 = 0
Deleting 16
List : [12, 0, 13, 17, 5, 12, 1, 12, 1, 12, 5, 5, 1, 6, 14, 12, 14, 14]
objectList.get(j)%2 = 1
objectList.get(j)%2 = 1
objectList.get(j)%2 = 1
objectList.get(j)%2 = 0
Deleting 12
List : [0, 13, 17, 5, 12, 1, 12, 1, 12, 5, 5, 1, 6, 14, 12, 14, 14]
objectList.get(j)%2 = 0
Deleting 12
List : [0, 13, 17, 5, 1, 12, 1, 12, 5, 5, 1, 6, 14, 12, 14, 14]
objectList.get(j)%2 = 0
Deleting 12
List : [0, 13, 17, 5, 1, 1, 12, 5, 5, 1, 6, 14, 12, 14, 14]
objectList.get(j)%2 = 1
objectList.get(j)%2 = 1
objectList.get(j)%2 = 0
Deleting 6
List : [0, 13, 17, 5, 1, 1, 12, 5, 5, 1, 14, 12, 14, 14]
objectList.get(j)%2 = 0
Deleting 12
List : [0, 13, 17, 5, 1, 1, 5, 5, 1, 14, 12, 14, 14]
objectList.get(j)%2 = 0
Deleting 14
List : [0, 13, 17, 5, 1, 1, 5, 5, 1, 12, 14, 14]
Final List : [0, 13, 17, 5, 1, 1, 5, 5, 1, 12, 14, 14]
...