Java implements iterable iterator

Interface Iterable

Implementing this interface allows an object to be the target of the enhanced for statement (sometimes called the «for-each loop» statement).

Method Summary

Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.

Method Details

iterator

forEach

Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception. Actions are performed in the order of iteration, if that order is specified. Exceptions thrown by the action are relayed to the caller. The behavior of this method is unspecified if the action performs side-effects that modify the underlying source of elements, unless an overriding class has specified a concurrent modification policy.

 for (T t : this) action.accept(t); 

spliterator

Report a bug or suggest an enhancement
For further API reference and developer documentation see the Java SE Documentation, which contains more detailed, developer-targeted descriptions with conceptual overviews, definitions of terms, workarounds, and working code examples. Other versions.
Java is a trademark or registered trademark of Oracle and/or its affiliates in the US and other countries.
Copyright © 1993, 2023, Oracle and/or its affiliates, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
All rights reserved. Use is subject to license terms and the documentation redistribution policy.

Читайте также:  Nginx include php conf

Источник

Java Iterable

The Java Iterable interface represents a collection of objects which is iterable — meaning which can be iterated. This means, that a class that implements the Java Iterable interface can have its elements iterated. You can iterate the objects of a Java Iterable in three ways: Via the , by obtaining a Java Iterator from the Iterable, or by calling the Java Iterable forEach() method. You will see examples of all three iteration methods later in this Java Iterable tutorial.

Java Iterable Tutorial Video

If you prefer video, I have a video version of this Java Iterable tutorial here:
Java Iterable Tutorial

Java Iterable Tutorial

Iterate an Iterable With the for-each Loop

The first way to iterate the elements of a Java Iterable is via the Java for-each loop loop. Below is an example showing how to iterate the elements of a Java List via the Java for-each loop. Since the Java List interface extends the Collection interface, and the Collection interface extends the Iterable interface, a List object can be used with the for-each loop.

This example first creates a new List and adds 3 elements to it. Then it uses a for-each loop to iterate the elements of the List , and print out the toString() value of each element.

Iterate an Iterable via an Iterator

The second way you can iterate the elements of a Java Iterable is by obtaining a Java Iterator from it by calling the Iterable iterator() method. You can then iterate through that Iterator like you would with any other Iterator. You can read more about the Java Iterator in my Java Iterator tutorial . Here is an example of iterating the elements of a Java Iterable (a Java List in this example):

List list = new ArrayList> <(); list.add("one"); list.add("two"); list.add("three"); Iteratoriterator = list.iterator(); while(iterator.hasNext())

Iterate an Iterable via its forEach() Method

The third way to iterate the elements of a Java Iterable is via its forEach() method. The forEach() method takes a Java Lambda Expression as parameter. This lambda expression is called once for each element in the Iterable. Here is an example of iterating the elements of an Iterable via its forEach() method:

Iterable Interface Definition

The Java Iterable interface has three methods of which only one needs to be implemented. The other two have default implementations. Here is the the definition of the Iterable interface:

public interface Iterable  < Iteratoriterator(); Spliterator spliterator(); void forEach(Consumer action); >

The method you must implement is named iterator() . This method must return a Java Iterator which can be used to iterate the elements of the object implementing the Iterable interface. Obtaining the Iterator happens behind the scenes, so you don’t see that done. The Java compiler takes care of generating the code for that, when you use a Iterable with the for-each loop.

Implementations of Iterable in Java

The Java Iterable interface ( java.lang.Iterable ) is one of the root interfaces of the Java Collections API. Therefore, there are several classes in Java that implements the Java Iterable interface. These classes can thus have their internal elements iterated.

There are also several Java interfaces that extends the Iterable interface. Classes implementing an interface which extends the Iterable interface thus also implement the Iterable interface. Such classes can also have their elements iterated.

The Collection interface extends Iterable , so all subtypes of Collection also implement the Iterable interface. For instance, both the Java List and Set interfaces extend the Collection interface, and thereby also the Iterable interface.

Implementing the Iterable Interface

How you implement this Iterable interface so that you can use it with the for-each loop, is explained in the text Implementing the Iterable Interface, in my Java Generics tutorial.

Here I will just show you a simple Iterable implementation example though:

public class Persons implements Iterable < private Listpersons = new ArrayList(); public Iterator iterator() < return this.persons.iterator(); >>

An instance of Persons can be used with the Java for-each loop like this:

Persons persons = . //obtain Persons instance with Person objects inside. for(Person person : persons) < // do something with person object. >

Obtaining a Spliterator

You can obtain a Java Spliterator from a Java Iterable via its spliterator() method. I won’t go into the the Spliterator interface here — just show how to obtain a Spliterator from an Iterable:

List list = new ArrayList> <(); list.add("one"); list.add("two"); list.add("three"); Spliteratorspliterator = list.spliterator();

Iterable Performance

If you are writing some code that needs to iterate a collection lots of times in a tight loop, let's say iterate a Java List thousands of times per second, iterating the List via the Java for-each loop is slower than iterating the list via a standard for-loop as seen here: ( ) .

The reason the for-each loop is slower is, that each iteration will call the List iterator() method, which will create a new Iterator object. Creating a new object thousands, perhaps even millions of times per second does have a small performance penalty compared to just iterating the List using a standard for-loop.

For most standard business applications where collections are iterated occasionally, this performance difference is irrelevant. It only matters for very tight loops that are executed thousands of times per second.

Источник

Паттерн Iterator

Java-университет

Как ты уже, вероятно, знаешь, в Java есть замечательный интерфейс Collection, реализующий интерфейс Iterator. Сразу оговорюсь, не следует путать интерфейс iterator с паттерном iterator в Java! И дабы внести ясность, для начала разберёмся именно с интерфейсом.

Дословно «Iterator» можно перевести как «переборщик». То есть это некая сущность, способная перебрать все элементы в коллекции. При этом она позволяет это сделать без вникания во внутреннюю структуру и устройство коллекций.

Представим на секунду, что iterator в Java отсутствует. В таком случае всем и каждому придётся нырнуть в самые глубины коллекций и по-настоящему разобраться, чем отличается, ArrayList от LinkedList и HashSet от TreeSet .

Методы, которые должен имплементировать Iterator

  • UnsupportedOperationException , если данный итератор не поддерживает метод remove() (в случае с read-only коллекциями, например)
  • IllegalStateException , если метод next() еще не был вызван, или если remove() уже был вызван после последнего вызова next() .
  • void add(E e) — вставляет элемент E в List ;
  • boolean hasPrevious() — вернет true , если при обратном переборе List имеются элементы;
  • int nextIndex() — вернет индекс следующего элемента;
  • E previous() — вернет предыдущий элемент листа;
  • int previousIndex() — вернет индекс предыдущего элемента;
  • void set(E e) — заменит элемент, возвращенный последним вызовом next() или previous() на элемент e .
 List list = new ArrayList<>(); list.add("Привет"); list.add("Обучающимся"); list.add("На"); list.add("JavaRush"); 
 Iterator iterator = list.iterator(); while (iterator.hasNext())

Сейчас будет «узкое место»: Java Collections как ты, вероятно, знаешь (а если не знаешь, разберись), расширяют интерфейс Iterable , но это не означает, что только List , Set и Queue поддерживают итератор. Для java Map iterator также поддерживается, но его необходимо вызывать для Map.entrySet() :

 Map map = new HashMap<>(); Iterator mapIterator = map.entrySet().iterator(); 

Тогда метод next() будет возвращать объект Entry , содержащий в себе пару «ключ»-«значение». Дальше все аналогично с List :

 while (mapIterator.hasNext()) < Map.Entryentry = mapIterator.next(); System.out.println("Key: " + entry.getKey()); System.out.println("Value: " + entry.getValue()); > 

Ты думаешь: «Стоп. Мы говорим про интерфейс, а в заголовке статьи написано «Паттерн». То есть, паттерн iterator – это интерфейс Iterator? Или интерфейс — это паттерн?» Если это слово встречается впервые, даю справку: паттерн — это шаблон проектирования, некое поведение, которого должен придерживаться класс или множество взаимосвязанных классов. Итератор в java может быть реализован для любого объекта, внутренняя структура которого подразумевает перебор, при этом можно изменить сигнатуру обсуждаемых методов. Главное при реализации паттерна – логика, которой должен придерживаться класс. Интерфейс итератор – частная реализация одноименного паттерна, применяемая как к готовым структурам ( List, Set, Queue, Map ), так и к прочим, на усмотрение программиста. Расширяя интерфейс Iterator, ты реализуешь паттерн, но для реализации паттерна не обязательно расширять интерфейс. Простая аналогия: все рыбы плавают, но не всё, что плавает – рыбы. В качестве примера я решил взять… слово. А конкретнее — существительное. Оно состоит из частей: приставки, корня, суффикса и окончания. Для частей слова создадим интерфейс WordPart и классы, расширяющие его: Prefix, Root, Suffix и Ending :

 interface WordPart < String getWordPart(); >static class Root implements WordPart < private String part; public Root(String part) < this.part = part; >@Override public String getWordPart() < return part; >> static class Prefix implements WordPart < private String part; public Prefix(String part) < this.part = part; >@Override public String getWordPart() < return part; >> static class Suffix implements WordPart < private String part; public Suffix(String part) < this.part = part; >@Override public String getWordPart() < return part; >> static class Ending implements WordPart < private String part; public Ending(String part) < this.part = part; >@Override public String getWordPart() < return part; >> 

Тогда класс Word (слово) будет содержать в себе части, а кроме них добавим целое число, отражающее количество частей в слове:

 public class Word < private Root root; private Prefix prefix; private Suffix suffix; private Ending ending; private int partCount; public Word(Root root, Prefix prefix, Suffix suffix, Ending ending) < this.root = root; this.prefix = prefix; this.suffix = suffix; this.ending = ending; this.partCount = 4; >public Word(Root root, Prefix prefix, Suffix suffix) < this.root = root; this.prefix = prefix; this.suffix = suffix; this.partCount = 3; >public Word(Root root, Prefix prefix) < this.root = root; this.prefix = prefix; this.partCount = 2; >public Word(Root root) < this.root = root; this.partCount = 1; >public Root getRoot() < return root; >public Prefix getPrefix() < return prefix; >public Suffix getSuffix() < return suffix; >public Ending getEnding() < return ending; >public int getPartCount() < return partCount; >public boolean hasRoot() < return this.root != null; >public boolean hasPrefix() < return this.prefix != null; >public boolean hasSuffix() < return this.suffix != null; >public boolean hasEnding()

Окей, у нас есть четыре перегруженных конструктора (для простоты, предположим, что суффикс у нас может быть только один). Существительное не может состоять из одной приставки, поэтому для конструктора с одним параметром будем устанавливать корень. Теперь напишем реализацию паттерна итератор: WordIterator, переопределяющий 2 метода: hasNext() и next() :

 public class WordIterator implements Iterator  < private Word word; private int wordPartsCount; public WordIterator(Word word) < this.word = word; this.wordPartsCount = word.getPartCount(); >@Override public boolean hasNext() < if (wordPartsCount == 4) < return word.hasPrefix() || word.hasRoot() || word.hasSuffix() || word.hasEnding(); >else if (wordPartsCount == 3) < return word.hasPrefix() || word.hasRoot() || word.hasSuffix(); >else if (wordPartsCount == 2) < return word.hasPrefix() || word.hasRoot(); >else if (wordPartsCount == 1) < return word.hasRoot(); >return false; > @Override public Word.WordPart next() throws NoSuchElementException < if (wordPartsCount try < if (wordPartsCount == 4) < return word.getEnding(); >if (wordPartsCount == 3) < return word.getSuffix(); >if (wordPartsCount == 2) < return word.getPrefix(); >return word.getRoot(); > finally < wordPartsCount--; >> > 
 public class Word implements Iterable < … @Override public Iteratoriterator() < return new WordIterator(this); >… > 

Источник

Оцените статью