2012-03-02 3 views
4

Я занимаюсь исследованием интерфейса java iterator и не могу понять, почему он так устроен.Что такое концепция java-итератора?

Почему Java-итератор использует hasNext и next вместо этого объединить их в один метод?

это типичное использование Java итератора

Iterator iter = //iterator from a list 
while(iter.hasNext()){ 
    Object obj = iter.next(); 
    // do something to obj 
} 

почему не

Iterator iter = //iterator from a list 
Object obj = null; 
try { 
    while(true){ 
     obj = iter.next(); 
     // do something to obj 
    } 
} catch (NoSuchElementException e) {} 

Очевидно, такой подход выглядит некрасиво, но что произойдет, если next возвращение нулевой, когда достигают до конца, а не бросить исключение ? чем код можно упростить

Iterator iter = //iterator from a list 
Object obj = null; 
while((obj = iter.next()) != null){ 
    // do something to obj 
} 

это как NSEnumerator в Objective-C работает

NSEnumerator *enumerator = // from an array 
while (id obj = [enumerator nextObject]) { 
    // do something to obj 
} 

Это увеличивает накладные расходы на реализацию пользовательских iterator.

Это также делает итератор Java не потокобезопасным. Например, у ArrayList есть один элемент. Два потока одновременно запрашивают один и тот же итератор для этого списка hasNext. Затем оба потока будут видеть true, и они будут вызывать next на этом итераторе. Потому что есть только один элемент, и итератор был задан дважды, что определенно приведет к состоянию исключения или ошибки.

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

Я думаю, что проблема в том, что проверка и обновление не происходят из-за атомарности, и я не могу понять, почему Java разработал интерфейс iterator.


Update

Я вижу, что нуль может быть значением, так что мой подход неверен. Но возможно ли какое-либо возможное обходное решение проблем, о которых я говорил выше?

+0

Вы беспокоитесь о ясности исходного кода или о стоимости выполнения вызова 'hasNext()', а затем 'next()'? –

+0

Я делаю проект университетского курса, связанный с итератором Java, поэтому просто хочу узнать об этом больше –

+0

Хорошо. В реальном мире ясность исходного кода почти всегда вызывает большую озабоченность, чем незначительные улучшения производительности. Вам придется выполнить * ужасный * цикл циклов до того, как стоимость дополнительного вызова метода станет существенным фактором времени выполнения. –

ответ

7

Ваше предложение не позволяет иметь значения null в коллекциях, так как он использует null как «ядовитую таблетку» для обнаружения конца итерации.

В очень редких случаях два потока совместно используют итератор, вам просто нужно обернуть его внутри какого-то пользовательского класса и синхронизировать доступ к итератору, чтобы сделать операцию check-then-act атомарной. Это необходимо в любом случае, даже если у итератора был только один метод, коллекция поддержки (ArrayList в вашем примере) не является потокобезопасной.

+0

oh .. я никогда не думал, что null можно поместить в список ... слишком привык думать в Objective-C way –

+0

+1 Но я бы добавил второе короткое предложение, в котором упоминалось причину этого. Имея два состояния, вы создаете 'next()' return null: null value или no more element. И чтобы исправить это, вам придется запретить значение «null» в качестве значения. –

+0

@FabianBarney: сделано. –

4

Ваше первое предложение - плохой дизайн, потому что он полагается на бросание и ловля исключения для состояния, которое, как известно, в конечном итоге произойдет. Исключения довольно дороги и предназначены только для «исключительных» ситуаций, которые обычно не должны возникать.

Ваше второе предложение не принимает во внимание, что Iterable s может иметь нулевые элементы.

Что касается бита безопасности нити, то стандарт Iterator s не должен быть потокобезопасным, и потребуется специальная реализация с добавленными накладными расходами. Это справедливо для большинства структур Java. Как JB Nizet notes, это больше зависит от структуры Iterable, которая является потокобезопасной, прежде чем ее можно будет использовать Iterator.

2

Для улучшения ясности исходного кода, использовать (пример с коллекцией струнного)

Iterable<String> values = ... // typically a Collection (List, Set...) 

for (String value : values) { 
    // do something with the value 
} 

Я согласен с предыдущими ответами о нуле-ограниченных коллекциях, контроль цикла с исключениями (который является зверской формой) и безопасностью потока ,

Из ваших предложений, нуль-ограничение коллекции является наименее неразумным, особенно если у вас есть политика «no nulls» в вашем коде. Однако это очень унииоматическая Java (редактировать: и нарушает контракт интерфейса Iterator), поэтому он может запутать будущих сопровождающих кода (отредактируйте и, возможно, вызовите тонкие и/или неожиданные ошибки).

Смежные вопросы