Внешний итератор против внутреннего итератора

Что такое внешний и внутренний итераторы в Java?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
35
0
17 739
6

Ответы 6

Это про кто контролирует итерацию.

Остальные подробности в этом вопросе Каковы преимущества интерфейса 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;
  }
});

Поскольку в Java 5 предпочтительным способом использования внешних итераторов было бы использование цикла for-each: for (Объект o: var) {// NOOP}, хотя это просто синтаксический сахар для явного итератора, использующего версию.

Alex 20.04.2014 21:25

@JohannZacharee не рассматривается как цикл foreach как внутренний итератор, поскольку у нас нет контроля над итератором?

denis631 05.09.2015 13:46

@ denis631 Да, я согласен, что цикл foreach действует аналогично внутреннему итератору. Я не использовал его в качестве примера, так как я понимаю, что Java преобразует их во внешний итератор во время компиляции. Я выбрал функциональный пример, чтобы более наглядно проиллюстрировать различия.

Johann Zacharee 11.09.2015 03:09

Я должен сообщить вам, что этот вопрос теперь является вторым результатом в Google для «внутреннего внешнего итератора», и отрывок гласит, что «быстрый поиск в Google мог бы дать вам ответ: ...» без включения ни одного ответа

Eevee 13.11.2016 03:34

Удалена ссылка на поиск Google, переформатирована, поэтому, надеюсь, результаты Google теперь будут включать соответствующий контент в отрывке.

Johann Zacharee 14.11.2016 21:36

Внешний итератор: - Используя это, мы должны перебирать все элементы один за другим и выполнять некоторую операцию, потому что у программиста есть контроль над этим, это внешний итератор.

Внутренний итератор: - Используя это, мы можем выполнять итерацию в соответствии с нашим условием, Программист может контролировать это, это внутренний итератор.

Давайте посмотрим на один пример ниже: 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();

В изображениях:

Очень красивый образ!

Philippe Fanaro 22.01.2020 18:09

Другие вопросы по теме