Jeśli mam listę zawierającą [alice, bob, abigail, charlie]
i chcę napisać iterator tak, aby iterował po elementach zaczynających się od „a”, czy mogę napisać własny? Jak mogę to zrobić ?
Jeśli mam listę zawierającą [alice, bob, abigail, charlie]
i chcę napisać iterator tak, aby iterował po elementach zaczynających się od „a”, czy mogę napisać własny? Jak mogę to zrobić ?
Odpowiedzi:
Pewnie. Iterator to po prostu implementacja java.util.Iterator
interfejsu. Jeśli używasz istniejącego iterowalnego obiektu (powiedzmy a LinkedList
) from java.util
, będziesz musiał albo podklasować go i nadpisać jego iterator
funkcję, aby zwrócić własną, albo zapewnić sposób zawijania standardowego iteratora w swojej specjalnej Iterator
instancji (która ma tę zaletę, że jest szerzej stosowany) itp.
Iterator
instancji ...” (i dzięki). :-)
Najlepszą opcją wielokrotnego użytku jest zaimplementowanie interfejsu Iterable i nadpisanie metody iterator ().
Oto przykład klasy podobnej do ArrayList implementującej interfejs, w której przesłaniasz metodę Iterator ().
import java.util.Iterator;
public class SOList<Type> implements Iterable<Type> {
private Type[] arrayList;
private int currentSize;
public SOList(Type[] newArray) {
this.arrayList = newArray;
this.currentSize = arrayList.length;
}
@Override
public Iterator<Type> iterator() {
Iterator<Type> it = new Iterator<Type>() {
private int currentIndex = 0;
@Override
public boolean hasNext() {
return currentIndex < currentSize && arrayList[currentIndex] != null;
}
@Override
public Type next() {
return arrayList[currentIndex++];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
return it;
}
}
Ta klasa implementuje interfejs Iterable przy użyciu typów Generics . Biorąc pod uwagę, że masz elementy tablicy, będziesz w stanie uzyskać instancję Iteratora, która jest potrzebną instancją używaną na przykład przez pętlę „foreach”.
Możesz po prostu utworzyć anonimową instancję iteratora bez tworzenia rozszerzającego Iteratora i skorzystać z wartości currentSize, aby zweryfikować miejsce, w którym możesz nawigować po tablicy (powiedzmy, że utworzyłeś tablicę o pojemności 10, ale masz tylko 2 elementy na 0 i 1). Instancja będzie miała swój licznik właściciela wskazujący, gdzie się znajduje, a wszystko, co musisz zrobić, to skorzystać z funkcji hasNext (), która sprawdza, czy bieżąca wartość nie jest null, oraz funkcji next (), która zwróci instancję Twojego currentIndex. Poniżej znajduje się przykład użycia tego interfejsu API ...
public static void main(String[] args) {
// create an array of type Integer
Integer[] numbers = new Integer[]{1, 2, 3, 4, 5};
// create your list and hold the values.
SOList<Integer> stackOverflowList = new SOList<Integer>(numbers);
// Since our class SOList is an instance of Iterable, then we can use it on a foreach loop
for(Integer num : stackOverflowList) {
System.out.print(num);
}
// creating an array of Strings
String[] languages = new String[]{"C", "C++", "Java", "Python", "Scala"};
// create your list and hold the values using the same list implementation.
SOList<String> languagesList = new SOList<String>(languages);
System.out.println("");
// Since our class SOList is an instance of Iterable, then we can use it on a foreach loop
for(String lang : languagesList) {
System.out.println(lang);
}
}
// will print "12345
//C
//C++
//Java
//Python
//Scala
Jeśli chcesz, możesz go również iterować za pomocą instancji Iterator:
// navigating the iterator
while (allNumbers.hasNext()) {
Integer value = allNumbers.next();
if (allNumbers.hasNext()) {
System.out.print(value + ", ");
} else {
System.out.print(value);
}
}
// will print 1, 2, 3, 4, 5
Wszystkie dokumenty znajdują się pod adresem http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html . Możesz rzucić okiem na bardziej kompletną implementację w moim osobistym kodzie Google .
Teraz, aby uzyskać efekty tego, czego potrzebujesz, myślę, że musisz podłączyć koncepcję filtru do Iteratora ... Ponieważ iterator zależy od następnych wartości, trudno byłoby zwrócić true w hasNext (), a następnie filtruj implementację next () z wartością, która nie zaczyna się na przykład od znaku „a”. Myślę, że musisz pobawić się dodatkowym Interatorem w oparciu o przefiltrowaną listę z wartościami z podanym filtrem.
for instance
, czy to gra słów?
Dobry przykład dla Iterable do obliczania silni
FactorialIterable fi = new FactorialIterable(10);
Iterator<Integer> iterator = fi.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
Krótki kod dla Java 1.8
new FactorialIterable(5).forEach(System.out::println);
Niestandardowa klasa iterowalna
public class FactorialIterable implements Iterable<Integer> {
private final FactorialIterator factorialIterator;
public FactorialIterable(Integer value) {
factorialIterator = new FactorialIterator(value);
}
@Override
public Iterator<Integer> iterator() {
return factorialIterator;
}
@Override
public void forEach(Consumer<? super Integer> action) {
Objects.requireNonNull(action);
Integer last = 0;
for (Integer t : this) {
last = t;
}
action.accept(last);
}
}
Niestandardowa klasa iteratora
public class FactorialIterator implements Iterator<Integer> {
private final Integer mNumber;
private Integer mPosition;
private Integer mFactorial;
public FactorialIterator(Integer number) {
this.mNumber = number;
this.mPosition = 1;
this.mFactorial = 1;
}
@Override
public boolean hasNext() {
return mPosition <= mNumber;
}
@Override
public Integer next() {
if (!hasNext())
return 0;
mFactorial = mFactorial * mPosition;
mPosition++;
return mFactorial;
}
}
To jest kompletny kod do napisania iteratora, który iteruje po elementach zaczynających się od „a”:
import java.util.Iterator;
public class AppDemo {
public static void main(String args[]) {
Bag<String> bag1 = new Bag<>();
bag1.add("alice");
bag1.add("bob");
bag1.add("abigail");
bag1.add("charlie");
for (Iterator<String> it1 = bag1.iterator(); it1.hasNext();) {
String s = it1.next();
if (s != null)
System.out.println(s);
}
}
}
Niestandardowa klasa iteratora
import java.util.ArrayList;
import java.util.Iterator;
public class Bag<T> {
private ArrayList<T> data;
public Bag() {
data = new ArrayList<>();
}
public void add(T e) {
data.add(e);
}
public Iterator<T> iterator() {
return new BagIterator();
}
public class BagIterator<T> implements Iterator<T> {
private int index;
private String str;
public BagIterator() {
index = 0;
}
@Override
public boolean hasNext() {
return index < data.size();
}
@Override
public T next() {
str = (String) data.get(index);
if (str.startsWith("a"))
return (T) data.get(index++);
index++;
return null;
}
}
}
Możesz zaimplementować swój własny Iterator. Twój iterator może być skonstruowany tak, aby zawijał Iterator zwracany przez List, lub możesz zachować kursor i użyć metody get (int index) listy. Musisz tylko dodać logikę do następnej metody Iteratora ORAZ metody hasNext, aby uwzględnić kryteria filtrowania. Będziesz także musiał zdecydować, czy Twój iterator będzie obsługiwał operację usuwania.
Oto pełna odpowiedź na to pytanie.
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
class ListIterator implements Iterator<String>{
List<String> list;
int pos = 0;
public ListIterator(List<String> list) {
this.list = list;
}
@Override
public boolean hasNext() {
while(pos < list.size()){
if (list.get(pos).startsWith("a"))
return true;
pos++;
}
return false;
}
@Override
public String next() {
if (hasNext())
return list.get(pos++);
throw new NoSuchElementException();
}
}
public class IteratorTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("alice", "bob", "abigail", "charlie");
ListIterator itr = new ListIterator(list);
while(itr.hasNext())
System.out.println(itr.next()); // prints alice, abigail
}
}
ListIterator
jest iteratorem tablicy, która zwraca elementy zaczynające się od „a”. NoSuchElementException
wyjątek.