[info]ru_java


ru.java

все о языке программирования java


Previous Entry в избранное рассказать другу Next Entry
Простенький вопросик
коровешка
[info]aefimov пишет в [info]ru_java
Что будет в напечатано после запуска? Не заглядывайте под кат, попытайтесь ответить сначала.

public class TestIterator {
    public static void main(String[] arg) {
        List<String> list = new ArrayList<String>(Arrays.asList("a", "b"));
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String string = it.next();
            list.remove(string);
        }
        System.out.println("list = " + list);
    }
}

Сюрприз, разрывающий мозг. Никакого ConcurrentModificationException не будет. А напечатано будет list = [b]. Это java version "1.6.0_06".
Будьте бдительны, на коллекциях из двух элементов это работает так как не должно работать.
Метки:

(комментировать)
hasNext не проверяет модификацию

Ну скажем так. Ведет он себя крайне странно. Посмотри что происходит с коллекций из одного и трех элементов.

Если бы он не проверял модификацию, напечатано бы было list = [a, b]

[info]earwin (Expand)
Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
+ дока на AbstractList.iterator()

никто в общем и не обещал этого эксепшна

Тем не менее никто не также ожидал, что это зависит от количества элементов в коллекции.

Скорее - от позиции того элемента на котором ты сделал модификацию.
Но если люди пишут "как повезёт", то они имеют полное легальное право вставить туда вызов рандома и чек на фазу луны :)

[info]cgem (Expand)
[info]earwin (Expand)
Любопытно, конечно, что hasNext() не проверяет modcount, но ничего разрывающего мозг, IMHO. Это не ошибка (итератор не обязан кидать CME), да и никто писать так не будет.

Надеюсь, вы не будете этот вопрос на интервью задавать :)

Ну вообщем мы задавали (я задавал), конечно. Теперь буду задавать с оговорками. Все же надо спрашивать это, имхо.

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

[info]earwin (Expand)
[info]earwin (Expand)
[info]earwin (Expand)
[info]earwin (Expand)
[info]earwin (Expand)
[info]earwin (Expand)
[info]earwin (Expand)
[info]earwin (Expand)
List<String> list = new ArrayList<String>(Arrays.asList("a", "b"));
Зачем new ArrayList<String>()? В исходниках jdk1.6.0_10:
This method also provides a convenient way to create a fixed-size list initialized to contain several elements:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

Arrays.asList вернет не модифицируемый лист.

jdk1.5.0_12 аналогичное поведение.

а я вот не знал про Arrays.asList("a", "b"). теперь знаю, спасибо!

Нельзя так делать. Удалять нужно через итератор.

если писать на java 5 то объекта итератора доступно не будет :)

for (String aList : list) {
list.remove(aList);
}

у думаю, что это нормально
вопрос, однако, возникает, почему мы до сих пор обсуждаем 1.6.0_06, когда на дворе уже _07

как бэ вот

(Анонимно)

2008-07-09 14:52 (UTC)

http://bugs.sun.com/view_bug.do?bug_id=4902078

Re: как бэ вот

[info]aefimov

2008-07-09 14:55 (UTC)

Closed, Will Not Fix, bug
Так я и думал. Бага это, всетаки.

[info]earwin (Expand)
Should в том то и дело. Но тут говорят что это не баг.

> Что будет в напечатано после запуска?
> Не заглядывайте под кат, попытайтесь ответить сначала.
Должно быть напечатано:
Compilation error:
while (it.hasNext()) {
String string = it.next();
list.remove(string); <--- КГ/АМ!!!
}

(-:

Шутка, но согласитесь - писать такое не надо.
И +1 к ораторам, считающим что это не баг.

Отвечаю вам и ораторам. CME это защита от такого кода. Я например расчитывал, что если человек не знает что удалять надо через итератор, то в рантайме ему об этом сообщат этим Exception-ом. Теперь представьте, что это не всегда, и что если он всетаки так написал по неопытности, то найти такую ошибку будет крайне сложно.

(Deleted comment)
(комментировать)