← Назад к вопросам
Может ли собственный объект быть частью for-each?
1.0 Junior🔥 211 комментариев
#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Собственный объект в for-each цикле
Да, можно! Для этого нужно реализовать интерфейс Iterable<T>. Разберу, как это работает и почему.
Основной механизм
For-each цикл в Java — это синтаксический сахар для работы с Iterable:
// Эта запись
for (String item : collection) {
System.out.println(item);
}
// Развёртывается компилятором в
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
Поэтому чтобы объект работал в for-each, он должен реализовать Iterable<T>.
Итерфейс Iterable
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
for (T t : this) {
action.accept(t);
}
}
}
Итерфейс Iterator имеет три метода:
public interface Iterator<T> {
boolean hasNext();
T next();
void remove();
}
Пример 1: Простая коллекция чисел
public class NumberRange implements Iterable<Integer> {
private final int start;
private final int end;
public NumberRange(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int current = start;
@Override
public boolean hasNext() {
return current < end;
}
@Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return current++;
}
};
}
}
// Использование
public class Main {
public static void main(String[] args) {
NumberRange range = new NumberRange(1, 5);
for (Integer num : range) {
System.out.println(num);
}
}
}
Пример 2: Коллекция студентов
public class Student {
private String name;
private int grade;
public Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
@Override
public String toString() {
return name + " (" + grade + ")";
}
}
public class StudentGroup implements Iterable<Student> {
private final List<Student> students = new ArrayList<>();
public void addStudent(Student student) {
students.add(student);
}
@Override
public Iterator<Student> iterator() {
return students.iterator();
}
}
Пример 3: Кастомный Iterator с фильтрацией
public class FilteredList<T> implements Iterable<T> {
private final List<T> items;
private final Predicate<T> filter;
public FilteredList(List<T> items, Predicate<T> filter) {
this.items = items;
this.filter = filter;
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
@Override
public boolean hasNext() {
while (index < items.size()) {
if (filter.test(items.get(index))) {
return true;
}
index++;
}
return false;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return items.get(index++);
}
};
}
}
Итого
- For-each работает с любым объектом, реализующим Iterable<T>
- Нужно реализовать метод iterator(), возвращающий Iterator<T>
- Iterator имеет три метода: hasNext(), next(), remove()
- Это позволяет создавать кастомные коллекции с любой логикой обхода