ถ้าฉันมีรายการที่มี[alice, bob, abigail, charlie]
และฉันต้องการเขียนตัววนซ้ำเพื่อให้มันวนซ้ำองค์ประกอบที่ขึ้นต้นด้วย 'a' ฉันสามารถเขียนของตัวเองได้หรือไม่ ฉันจะทำเช่นนั้นได้อย่างไร?
ถ้าฉันมีรายการที่มี[alice, bob, abigail, charlie]
และฉันต้องการเขียนตัววนซ้ำเพื่อให้มันวนซ้ำองค์ประกอบที่ขึ้นต้นด้วย 'a' ฉันสามารถเขียนของตัวเองได้หรือไม่ ฉันจะทำเช่นนั้นได้อย่างไร?
คำตอบ:
แน่นอน ตัววนซ้ำเป็นเพียงการนำjava.util.Iterator
อินเทอร์เฟซมาใช้ หากคุณกำลังใช้อ็อบเจ็กต์ที่ทำซ้ำได้ที่มีอยู่ (เช่น a LinkedList
) จากjava.util
คุณจะต้องทำการคลาสย่อยและแทนที่iterator
ฟังก์ชันของมันเพื่อให้คุณส่งคืนของคุณเองหรือระบุวิธีการรวมตัวทำซ้ำมาตรฐานในIterator
อินสแตนซ์พิเศษของคุณ(ซึ่ง มีข้อได้เปรียบในการใช้งานในวงกว้างมากขึ้น) ฯลฯ
Iterator
อินสแตนซ์พิเศษของคุณ... " (และขอบคุณ) :-)
ตัวเลือกที่สามารถใช้ซ้ำได้ดีที่สุดคือการใช้อินเทอร์เฟซที่ทำซ้ำได้และแทนที่ method 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;
}
}
ชั้นนี้การดำเนินการอินเตอร์เฟซที่ใช้ Iterable Generics เมื่อพิจารณาว่าคุณมีองค์ประกอบของอาร์เรย์คุณจะสามารถรับอินสแตนซ์ของ Iterator ซึ่งเป็นอินสแตนซ์ที่จำเป็นที่ใช้โดยลูป "foreach" เป็นต้น
คุณสามารถสร้างอินสแตนซ์แบบไม่ระบุตัวตนของตัววนซ้ำได้โดยไม่ต้องสร้าง Iterator ที่ขยายและใช้ประโยชน์จากค่าของ currentSize เพื่อตรวจสอบว่าคุณสามารถนำทางไปยังตำแหน่งใดได้บ้าง (สมมติว่าคุณสร้างอาร์เรย์ที่มีความจุ 10 แต่คุณมีเพียง 2 องค์ประกอบที่ 0 และ 1) อินสแตนซ์จะมีตัวนับเจ้าของว่ามันอยู่ที่ไหนและสิ่งที่คุณต้องทำคือเล่นกับ hasNext () ซึ่งจะตรวจสอบว่าค่าปัจจุบันไม่ใช่ค่าว่างหรือไม่และค่าถัดไป () ซึ่งจะส่งคืนอินสแตนซ์ของ currentIndex ของคุณ ด้านล่างนี้คือตัวอย่างการใช้ 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
ตอนนี้เพื่อให้ได้เอฟเฟกต์ของสิ่งที่คุณต้องการฉันคิดว่าคุณต้องเสียบแนวคิดของตัวกรองใน Iterator ... เนื่องจากตัววนซ้ำขึ้นอยู่กับค่าถัดไปจึงยากที่จะคืนค่าจริงใน hasNext () แล้ว กรองการใช้งาน next () ด้วยค่าที่ไม่ได้ขึ้นต้นด้วยอักขระ "a" เช่น ฉันคิดว่าคุณต้องเล่นกับผู้โต้ตอบรองตามรายการที่กรองด้วยค่าด้วยตัวกรองที่กำหนด
for instance
นั่นคือการเล่นสำนวน?
ตัวอย่างที่ดีสำหรับ 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);
คลาสที่ทำซ้ำได้เอง
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);
}
}
คลาส Iterator ที่กำหนดเอง
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;
}
}
นี่คือรหัสที่สมบูรณ์ในการเขียนตัววนซ้ำเพื่อให้มันวนซ้ำองค์ประกอบที่ขึ้นต้นด้วย '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);
}
}
}
คลาส Iterator ที่กำหนดเอง
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;
}
}
}
คุณสามารถใช้ Iterator ของคุณเองได้ ตัววนซ้ำของคุณสามารถสร้างขึ้นเพื่อห่อ Iterator ที่ส่งคืนโดย List หรือคุณสามารถเก็บเคอร์เซอร์ไว้และใช้วิธี List's get (int index) คุณเพียงแค่ต้องเพิ่มตรรกะในวิธีการถัดไปของ Iterator ของคุณและวิธี hasNext เพื่อพิจารณาเกณฑ์การกรองของคุณ คุณจะต้องตัดสินใจด้วยว่าตัววนซ้ำของคุณจะรองรับการลบหรือไม่
นี่คือคำตอบที่สมบูรณ์สำหรับคำถาม
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
เป็นตัววนซ้ำสำหรับอาร์เรย์ซึ่งส่งคืนองค์ประกอบที่ขึ้นต้นด้วย 'a' NoSuchElementException
ข้อยกเว้นที่ถูกต้อง