AnyLogic
Развернуть
Размер шрифта

Цикл 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
    Agent e = queue.get(i); // получение i-ого агента
    if( e.resourceUnits == null || e.resourceUnits.isEmpty() ) { // проверка
        queue.remove( e ); //удаление агента из очереди queue
        break; // выход из цикла
    }
}

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

Как мы можем улучшить эту статью?