Удаление отрицательных значений из Set - PullRequest
2 голосов
/ 27 октября 2019

Я ожидал, что метод remove () удаляет отрицательные значения и печатает только положительные целые числа, но на выходе получается -1 -2 -3 4

 import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;

    public class GenericSetTester {
        public static void main(String[] args) {

            Set<Integer> integerSet = new HashSet<>();

            integerSet.add(0);
            integerSet.add(1);
            integerSet.add(2);
            integerSet.add(3);
            integerSet.add(4);
            integerSet.add(-1);
            integerSet.add(-2);
            integerSet.add(-3);

            for(Iterator<Integer> in = integerSet.iterator(); in.hasNext();){
                if(in.next() < 0)
                    in.remove();
                   int i = in.next();
                System.out.printf("%d ",i);
            }
        }
    }

Ответы [ 4 ]

1 голос
/ 27 октября 2019

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

Рассмотримпорядок, в котором элементы вашего Set повторяются:

0 // consumed by if(in.next() < 0), which returns false, element not removed
-1 // consumed by int i = in.next();, and later printed -1
1 // consumed by if(in.next() < 0), which returns false, element not removed
-2 // consumed by int i = in.next();, and later printed -2
2 // consumed by if(in.next() < 0), which returns false, element not removed
-3 // consumed by int i = in.next();, and later printed -3
3 // consumed by if(in.next() < 0), which returns false, element not removed
4 // consumed by int i = in.next();, and later printed 4

Как видите, ваш цикл не удаляет какой-либо элемент из Set и печатает только половину элементов (-1 -2 -3 4).

Это должно быть:

for (Iterator<Integer> in = integerSet.iterator(); in.hasNext();) {
    int i = in.next();
    if (i < 0)
        in.remove();
    else
        System.out.printf("%d ",i);
}

Как предположил Тим, если вы напечатаете Set после цикла, вы увидите, содержит ли он толькоэлементы, которые он должен содержать. Ваша петля станет:

for(Iterator<Integer> in = integerSet.iterator(); in.hasNext();){
    if(in.next() < 0)
        in.remove();
}
System.out.println (integerSet);
0 голосов
/ 27 октября 2019

лямбда, которая сохраняет исходное Set

integerSet.removeAll( integerSet.stream().filter( i -> i < 0 ).collect( Collectors.toList() ) );
…

… или просто: Решение Хольгера - см. Комментарий ниже

integerSet.removeIf( i -> i < 0 );
0 голосов
/ 27 октября 2019

Происходит следующее: IntegerSet добавляет числа в следующем порядке (хотя я не знаю почему): 0: 0 1: -1 2: 1 3: -2 4: 2 5: -3 6: 3 7: 4

Вот почему, если вы делаете цикл, он сначала проверяет, меньше ли следующий из 0, чем 0. Что вернет истину, поскольку -1 меньше даного 0. Поэтому 0 будет удалено. Затем он проверяет следующее из -1, которое равно 1, меньше 0. Что вернет false. Так что -1 не будет удален.

Вот почему выход -1 -2 -3 4

0 голосов
/ 27 октября 2019

Ответ @Eran исправляет ваш текущий подход. Обратите внимание, что потоки предоставляют другой способ удовлетворить ваши требования:

Integer[] array = new Integer[] {0, 1, 2, 3, 4, -1, -2, -3};
Set<Integer> integerSet = new HashSet<>(Arrays.asList(array));
integerSet = integerSet.stream()
    .filter(i -> i >= 0)
    .collect(Collectors.toSet());
...