Цикл for

В Java есть две формы цикла for

Начнем с более простой в использовании "улучшенной" версией фикла for:

for( <тип элемента> <имя> : <коллекция> ) {
    <строки кода (statements)> //тело цикла, выполняемое для каждого элемента
}

Эта форма используется для итерирования по элементам массивов и коллекций. В том случае, если Вам нужно сделать что-либо с каждым элементом коллекции, мы рекомендуем использовать эту форму цикла, потому что она легче читается и является более компактной, а также поддерживается всеми типами коллекций (в отличие от итерирования по индексу).

Пример: в агентной модели есть портфолио фирмы - производителя продукта моделируется как реплицированный объект products (как известно, реплицированный объект является коллекцией). Следующий код проходит в цикле по всем продуктам в портфолио и удаляет те, у которых ожидаемый коэффициент окупаемости инвестиций меньше некоторого допустимого минимума:

for( Product p : products ) {
    if( p.getEstimatedROI() < minROI )
        p.kill();
}

Другой пример: приведенный ниже цикл подсчитывает количество проданных билетов в кинотеатре. Места моделируются как Java массив seats с элементами типа boolean (значение true означает, что билет на данное место продан):

boolean[] seats = new boolean[600]; //объявление массива

int nsold = 0;
for( boolean sold : seats )
    if( sold )
        nsold++;

Обратите внимание, что если тело цикла содержит только одну строку кода, то фигурные скобки {…} могут быть опущены. В приведенном выше коде скобки опущены как в цикле for, так и в операторе if.

Другая, более общая, форма цикла for обычно используется для итерирования по индексу. Вы можете добавить в строку объявления цикла код инициализации (например, объявление переменной - индекса), условие, которое будет проверяться перед каждой итерацией для определения того, должен ли цикл продолжать свое выполнение, а также код, который должен выполняться после каждой итерации (в котором можно, например, увеличивать значение переменной - индекса):

for( <инициализация>; <условие продолжения>; <инкремент> ) {
    <строки кода>
}

Следующий цикл находит все круги в группе фигур и меняет их цвет заливки на красный:

for( int i=0; i<group.size(); i++ ) { //цикл итерирования по индексу
    Object obj = group.get( i ); //получение i-го элемента группы
    if( obj instanceof ShapeOval ) { //проверка того, является ли этот элемент объектом класса ShapeOval – класса овала в AnyLogic
        ShapeOval ov = (ShapeOval)obj; //если это овал, "приводим" объект к классу ShapeOval
        ov.setFillColor( red ); //меняем цвет заливки на красный
    }
}

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

Многие объекты Основной библиотеки также используют итерирование по индексу. Например, следующий код проходит в цикле по всем находящимся в очереди queue заявкам, от конца до начала, и удаляет первую найденную заявку, которая не владеет в текущий момент никакими ресурсами:

for( int i=queue.size()-1; i>=0; i–– ) { //индекс i меняет значение от queue.size()–1 до 0
    Entity e = queue.get(i); //получение i-й заявки
    if( e.resourceUnits == null || e.resourceUnits.isEmpty() ) { //проверка
        queue.remove( e ); //удаление заявки из очереди queue
        break; //выход из цикла
    }
}

Обратите внимание, что в этом цикле индекс декрементируется (уменьшается на 1) после каждой итерации, и соответственно условие продолжения проверяет, не достиг ли индекс 0. При нахождении заявки, удовлетворяющей нашему условию, мы удаляем ее, и продолжать выполнение цикла далее нам не нужно. Оператор break осуществляет мгновенный выход из цикла. Если заявка не найдена, то цикл завершает свое выполнение естественным образом, когда после очередной итерации индекс становится равен -1.