Это про кто контролирует итерацию.
Остальные подробности в этом вопросе Каковы преимущества интерфейса Iterator в Java?
Нашел вот такой описание:
Внешние и внутренние итераторы.
Внешние итераторы - когда итерация контролируется объектом коллекции, мы говорим, что у нас есть внешний итератор.
В таких языках, как .net или java, очень легко создавать внешние итераторы. В нашей классической реализации реализован внешний итератор. В следующем примере используется внешний итератор:
// using iterators for a clloection of String objects:
// using in a for loop
for (Iterator it = options.iterator(); it.hasNext(); ) {
String name = (String)it.next();
System.out.println(name);
}
// using in while loop
Iterator name = options.iterator();
while (name.hasNext() ){
System.out.println(name.next() );
}
// using in a for-each loop (syntax available from java 1.5 and above)
for (Object item : options)
System.out.println(((String)item));
Внутренние итераторы - когда итератор управляет им, у нас есть внутренний итератор.
С другой стороны, реализация и использование внутренних итераторов действительно сложно. Когда используется внутренний итератор, это означает, что запускаемый код делегируется агрегатному объекту. Например, в языках, которые предлагают поддержку для этого, легко вызвать внутренние итераторы:
collection do: [:each | each doSomething] (Smalltalk)
Основная идея - передать код для выполнения в коллекцию. Затем коллекция вызовет внутренний метод doSomething для каждого из компонентов. В C++ можно отправить метод doMethod как указатель. В C#, .NET или VB.NET можно отправить метод как делегат. В java необходимо использовать шаблон проектирования Functor
. Основная идея - создать базовый интерфейс только с одним методом (doSomething). Затем метод будет реализован в классе, реализующем интерфейс, и этот класс будет передан в коллекцию для выполнения итерации. Дополнительные сведения см. В шаблоне проектирования Functor
.
Когда вы получаете итератор и переступаете через него, это внешний итератор.
for (Iterator iter = var.iterator(); iter.hasNext(); ) {
Object obj = iter.next();
// Operate on obj
}
Когда вы передаете объект функции методу для выполнения по списку, это внутренний итератор.
var.each( new Functor() {
public void operate(Object arg) {
arg *= 2;
}
});
@JohannZacharee не рассматривается как цикл foreach как внутренний итератор, поскольку у нас нет контроля над итератором?
@ denis631 Да, я согласен, что цикл foreach действует аналогично внутреннему итератору. Я не использовал его в качестве примера, так как я понимаю, что Java преобразует их во внешний итератор во время компиляции. Я выбрал функциональный пример, чтобы более наглядно проиллюстрировать различия.
Я должен сообщить вам, что этот вопрос теперь является вторым результатом в Google для «внутреннего внешнего итератора», и отрывок гласит, что «быстрый поиск в Google мог бы дать вам ответ: ...» без включения ни одного ответа
Удалена ссылка на поиск Google, переформатирована, поэтому, надеюсь, результаты Google теперь будут включать соответствующий контент в отрывке.
Внешний итератор: - Используя это, мы должны перебирать все элементы один за другим и выполнять некоторую операцию, потому что у программиста есть контроль над этим, это внешний итератор.
Внутренний итератор: - Используя это, мы можем выполнять итерацию в соответствии с нашим условием, Программист может контролировать это, это внутренний итератор.
Давайте посмотрим на один пример ниже: Q - мы хотим добавить сумму к целому числу из списка, которое равно или больше 5.
package java8;
import java.util.ArrayList;
import java.util.List;
public class IteratorExpr {
public static void main(String[] args) {
List<Integer> myList = new ArrayList<Integer>();
for(int i=0; i<10; i++) myList.add(i);
//Get sum of all value which is more than 5 using External Iterator
int sum = 0;
for(int no: myList) {
if (no >=5) {
sum += no;
}
}
System.out.println("Sum of numbers using External api : "+sum);
int summ = myList.stream()
.filter(p->p>=5)
.mapToInt(p->p).sum();
System.out.println("Sum of numbers using internal api : "+summ);
}
}
Выход :
Sum of numbers using External api : 35
Sum of numbers using internal api : 35
Я нашел ответ через здесь.
Внутренние итераторы управляют итерациями в фоновом режиме. Это оставляет программисту просто декларативно кодировать то, что должно быть сделано с элементами коллекции, вместо того, чтобы управлять итерацией и следить за тем, чтобы все элементы обрабатывались один за другим. Бывший:
public class InternalIterator {
public static void main(String args[]){
List<String> namesList=Arrays.asList("Tom", "Dick", "Harry");
namesList.forEach(name -> System.out.println(name));//Internal Iteration
}
}
При использовании внешних итераторов ответственность за повторение элементов и обеспечение того, чтобы эта итерация учитывала общее количество записей, наличие дополнительных записей для повторения и т. д., Лежит на программисте.
Бывший:
import java.util.*;
public class ExternalIterator {
public static void main(String args[]){
List<String> namesList=Arrays.asList("Tom", "Dick", "Harry");
for(String name:namesList){
System.out.println(name);
}
}
}
Пример внешнего итератора:
int count = 0;
Iterator<SomeStaff> iterator = allTheStaffs.iterator();
while(iterator.hasNext()) {
SomeStaff staff = iterator.next();
if (staff.getSalary() > 25) {
count++;
}
}
Пример внутреннего итератора:
long count = allTheStaffs.stream()
.filter(staff -> staff.getSalary() > 25)
.count();
В изображениях:
Очень красивый образ!
Поскольку в Java 5 предпочтительным способом использования внешних итераторов было бы использование цикла for-each: for (Объект o: var) {// NOOP}, хотя это просто синтаксический сахар для явного итератора, использующего версию.