[alice, bob, abigail, charlie]
を含むリストがあり、 'a'で始まる要素を反復処理するイテレータを作成する場合、独自に作成できますか?どうやってやるの ?
承知しました。イテレータは、 Java.util.Iterator
インターフェースの単なる実装です。 Java.util
の既存の反復可能なオブジェクト(たとえば、LinkedList
)を使用している場合、サブクラス化し、そのiterator
関数をオーバーライドして、独自のオブジェクトを返すか、手段を提供する必要があります。特別なIterator
インスタンスで標準イテレータをラップすること(より広く使用されるという利点があります)など。
最適な再利用可能なオプションは、インターフェイスIterableを実装し、メソッドiterator()をオーバーライドすることです。
以下に、インターフェイスを実装するクラスのようなArrayListの例を示します。ここでは、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;
}
}
このクラスは、 Generics を使用してIterableインターフェイスを実装します。配列の要素があることを考慮すると、イテレータのインスタンスを取得できます。イテレータは、たとえば「foreach」ループで使用される必要なインスタンスです。
拡張イテレータを作成せずにイテレータの匿名インスタンスを作成し、currentSizeの値を利用して、配列をナビゲートできる場所まで検証できます(容量が10の配列を作成したが、2 0および1の要素)。インスタンスには現在の所有者カウンターがあり、現在の値がnullではないことを確認するhasNext()と、currentIndexのインスタンスを返すnext()で遊ぶだけです。以下はこの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
必要に応じて、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
Foreachのドキュメントは http://download.Oracle.com/javase/1,5.0/docs/guide/language/foreach.html にあります。私の個人的な練習でより完全な実装を見ることができます google code 。
さて、必要なものの効果を得るには、イテレータにフィルタの概念をプラグインする必要があると思います...イテレータは次の値に依存するため、hasNext()でtrueを返すのは難しいでしょう。たとえば、文字「a」で始まらない値でnext()実装をフィルタリングします。与えられたフィルターの値を持つフィルターされたリストに基づいて、2次インターレーターをいじる必要があると思います。
Iterableの階乗計算の良い例
FactorialIterable fi = new FactorialIterable(10);
Iterator<Integer> iterator = fi.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
Java 1.8の短いコード
new FactorialIterable(5).forEach(System.out::println);
カスタムIterableクラス
public class FactorialIterable implements Iterable<Integer> {
private final FactorialIteartor factorialIteartor;
public FactorialIterable(Integer value) {
factorialIteartor = new FactorialIteartor(value);
}
@Override
public Iterator<Integer> iterator() {
return factorialIteartor;
}
@Override
public void forEach(Consumer<? super Integer> action) {
Objects.requireNonNull(action);
Integer last = 0;
for (Integer t : this) {
last = t;
}
action.accept(last);
}
}
カスタムイテレータクラス
public class FactorialIteartor implements Iterator<Integer> {
private final Integer mNumber;
private Integer mPosition;
private Integer mFactorial;
public FactorialIteartor(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;
}
}
これは、「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);
}
}
}
カスタムイテレータークラス
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;
}
}
}
独自のイテレータを実装できます。イテレータは、リストから返されたイテレータをラップするように構築するか、カーソルを保持してリストのget(int index)メソッドを使用できます。イテレータのnextメソッドとhasNextメソッドにロジックを追加するだけで、フィルタリング基準を考慮することができます。また、イテレータが削除操作をサポートするかどうかを決定する必要があります。