← Назад к вопросам

В чем разница между for и for-in?

1.6 Junior🔥 21 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между for и for-in

В Dart существует два способа итерации по коллекциям: традиционный for цикл и for-in цикл. Они используются в разных ситуациях и имеют свои преимущества.

Синтаксис и использование

for — традиционный цикл

Использует индекс для доступа к элементам:

for (int i = 0; i < list.length; i++) {
  print(list[i]);
}

// Более короткий синтаксис
for (var i = 0; i < list.length; i++) {
  print(list[i]);
}

for-in — цикл по значениям

Прямая итерация по элементам без индекса:

for (var item in list) {
  print(item);
}

// С типом
for (String item in names) {
  print(item);
}

Основные отличия

1. Доступ к индексу

for — имеет доступ к индексу:

final names = ['Alice', 'Bob', 'Charlie'];

for (int i = 0; i < names.length; i++) {
  print('${i + 1}. ${names[i]}'); // 1. Alice, 2. Bob, 3. Charlie
}

for-in — индекс недоступен (нужна работа):

final names = ['Alice', 'Bob', 'Charlie'];

int index = 0;
for (var name in names) {
  print('${index + 1}. $name'); // Пришлось вводить отдельную переменную
  index++;
}

// Или используй .asMap()
for (var entry in names.asMap().entries) {
  print('${entry.key + 1}. ${entry.value}');
}

2. Производительность

for — немного быстрее на больших коллекциях (прямой доступ по индексу):

// Очень быстро
for (int i = 0; i < hugeList.length; i++) {
  process(hugeList[i]);
}

for-in — использует Iterator (немного медленнее, но незначительно):

// Немного медленнее, но практически не заметно
for (var item in hugeList) {
  process(item);
}

В большинстве случаев эта разница пренебрежима.

3. Типы, с которыми работают

for — работает с коллекциями, имеющими .length и индексацию:

final list = [1, 2, 3];
final string = 'Hello';
final range = List.generate(10, (i) => i);

// for работает с ними
for (int i = 0; i < list.length; i++) { ... }
for (int i = 0; i < string.length; i++) { ... }
for (int i = 0; i < range.length; i++) { ... }

for-in — работает с любыми Iterable (включая Stream):

final list = [1, 2, 3];
final set = {1, 2, 3};
final map = {'a': 1, 'b': 2};
final string = 'Hello';

// for-in работает со всеми
for (var item in list) { ... }
for (var item in set) { ... }         // for не работает с Set!
for (var key in map.keys) { ... }     // for не работает с keys!
for (var char in string.split('')) { ... }

Практические примеры

Пример 1: Простая итерация

final fruits = ['Apple', 'Banana', 'Cherry'];

// ❌ Усложнённо с for
for (int i = 0; i < fruits.length; i++) {
  print(fruits[i]);
}

// ✅ Просто с for-in
for (var fruit in fruits) {
  print(fruit);
}

Пример 2: Нужен индекс

final items = ['First', 'Second', 'Third'];

// ✅ for — естественнее
for (int i = 0; i < items.length; i++) {
  print('${i}: ${items[i]}');
}

// for-in — нужны хитрости
for (var entry in items.asMap().entries) {
  print('${entry.key}: ${entry.value}');
}

Пример 3: Работа с Set

final tags = {'flutter', 'dart', 'mobile'};

// ❌ for не работает с Set
for (int i = 0; i < tags.length; i++) {
  // Синтаксическая ошибка!
}

// ✅ for-in работает прекрасно
for (var tag in tags) {
  print(tag);
}

Пример 4: Работа с Map

final user = {'name': 'John', 'age': 30};

// ❌ for не подходит
// Не можем итерировать по Map напрямую

// ✅ for-in с keys
for (var key in user.keys) {
  print('$key: ${user[key]}');
}

// ✅ for-in с entries (ещё лучше)
for (var entry in user.entries) {
  print('${entry.key}: ${entry.value}');
}

Пример 5: Вложенные циклы

final matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
];

// for — если нужны индексы
for (int i = 0; i < matrix.length; i++) {
  for (int j = 0; j < matrix[i].length; j++) {
    print('[$i][$j] = ${matrix[i][j]}');
  }
}

// for-in — если индексы не нужны
for (var row in matrix) {
  for (var value in row) {
    print(value);
  }
}

Эволюция: forEach и другие методы

forEach — функциональный подход

final items = [1, 2, 3, 4, 5];

// Современный подход
items.forEach((item) {
  print(item);
});

// С индексом
items.asMap().forEach((index, item) {
  print('$index: $item');
});

Functional approach (map, where, reduce)

// Лучший подход для трансформаций
final numbers = [1, 2, 3, 4, 5];

// Транформация
final doubled = numbers.map((n) => n * 2);

// Фильтрация
final evens = numbers.where((n) => n.isEven);

// Все вместе
final result = numbers
  .where((n) => n.isEven)
  .map((n) => n * 2)
  .toList();

Таблица сравнения

                    for                 for-in
──────────────────────────────────────────────────
Индекс              Есть                Нет
Производительность  Чуть быстрее       Нормальная
Читаемость          Хуже               Лучше
Итерируемость       List, String       Iterable, Set, Map
Проходы в обратном  Легко              Сложно
Остановка цикла     break/continue     break/continue
Нестанд. шаг        for(i+=2) / i--    Нельзя

Best Practices

Используй for-in когда:

  • Нужна простая итерация
  • Работаешь с Set или Map
  • Индекс не важен
  • Читаемость критична
for (var user in users) {
  updateUI(user);
}

Используй for когда:

  • Нужен индекс
  • Нужна особая логика итерации (i += 2, i--)
  • Работаешь со строками по символам
for (int i = 0; i < text.length; i++) {
  print(text[i]);
}

Используй forEach / map когда:

  • Нужна функциональная трансформация
  • Работаешь с коллекциями
users.forEach((user) => print(user.name));
users.map((u) => u.email).toList();

Современное правило: предпочитай for-in и функциональные методы, используй for только когда действительно нужен индекс.

Вывод

  • for — классический цикл с индексом, используй когда нужен контроль итерации
  • for-in — простая итерация по значениям, используй по умолчанию
  • for-in поддерживает больше типов (Set, Map, Iterable)
  • for немного быстрее, но разница незначительна

В современном Dart лучше начинать с for-in, и только при необходимости переходить на for.