[英]How to implement a Nested List Iterator
我在一次采訪中被問到這個問題:
“如何實現自定義嵌套列表迭代器?”
方法next()
應該首先返回每個列表的第一個元素,然后是第二個元素,依此類推。
輸入示例:
[[1,2,3],[4,5],[6],[],[7,8,9]]
Output :
[1,4,6,7,2,5,8,3,9]
存根代碼:
public class CustomListIterator implements Iterator<Integer> {
public CustomListIterator(List<List<Integer>> nestedList) {
}
@Override
public boolean hasNext() {
}
@Override
public Integer next() {
}
}
如何實施?
您可以通過使用ListIterator
和Iterator
的組合來實現。 這種方法可以讓您擺脫維持任何職位的必要性。
總體思路是創建一個迭代器列表和一個迭代這些列表的listIterator 。
方法hasNext()
對列表執行迭代並檢查它是否至少有一個未耗盡的迭代器。
方法next()
更復雜一些。 首先,它將嘗試將listIterator從最后一個元素后面的position“重置”到列表第一個元素之前的position。
然后在循環內部,它會檢查列表中的下一個迭代器,如果這個迭代器用盡,它將被刪除。 為了使此操作快速進行,迭代器存儲在LinkedList
中。 如果找到該元素,它將被返回。
為了處理“空”迭代器出現在列表末尾並且listIterator到達最后一個 position 但列表中可能還有一些未訪問的迭代器的情況,在循環的最后放置了一個額外的檢查。
在下面的實現中,為了簡潔起見,我在hasNext()
和構造函數中使用了流。 即使您對流不太熟悉,整體邏輯也應該清晰,並且您可以輕松地將其替換為流。
public class CustomListIterator<T> implements Iterator<T> {
private List<Iterator<T>> iterators;
private ListIterator<Iterator<T>> listIterator;
public CustomListIterator(List<List<T>> nestedList) {
this.iterators = nestedList.stream()
.map(List::iterator)
.collect(Collectors.toCollection(LinkedList::new));
this.listIterator = iterators.listIterator();
}
@Override
public boolean hasNext() {
return iterators.stream().anyMatch(Iterator::hasNext);
}
@Override
public T next() {
if (!iterators.isEmpty() && !listIterator.hasNext()) tryReset();
while (!iterators.isEmpty() && listIterator.hasNext()) {
Iterator<T> current = listIterator.next();
if (!current.hasNext()) {
listIterator.remove(); // removing exhausted iterator
} else {
return current.next();
}
if (!listIterator.hasNext()) tryReset();
}
throw new IllegalStateException();
}
private void tryReset() {
while (listIterator.hasPrevious()) {
listIterator.previous();
}
}
}
main()
- 演示
public static void main(String[] args) {
List<List<Integer>> numbers =
List.of(List.of(1, 4, 6, 7),
List.of(),
List.of(2, 5),
List.of(3));
CustomListIterator<Integer> nestedIterator = new CustomListIterator<>(numbers);
while (nestedIterator.hasNext()) {
System.out.print(nestedIterator.next() + "\t");
}
}
Output
1 2 3 4 5 6 7
要實現一個迭代器,我們需要一個 cursor 來跟蹤我們當前所在的元素。 根據底層數據結構,cursor 可以是索引或指針,它將用於從一個元素前進到另一個元素。 這是在 next() 方法中完成的,該方法返回當前元素,cursor 前進到下一個元素。
因為在您的問題中,您要求為通用列表提供自定義迭代器(不是專門的 ArrayList 或 LinkedList); 我決定使用一個 int 索引作為 cursor 來指向兩個數據結構的元素。
為了回答您的問題,我將您的列表列表描繪為具有不同長度行的矩陣,我們首先遍歷當前列的行(外部列表光標),然后移動到下一列(內部列表或子列表光標)。
class CustomListIteratorVert implements Iterator<Integer> {
private List<List<Integer>> nestedList;
private int listCur, subListCur;
//value to understand when the iteration has completed since the "column" cursor has reached its end
private int maxSublistSize;
public CustomListIteratorVert(List<List<Integer>> nestedList) {
this.nestedList = nestedList;
this.listCur = 0;
this.subListCur = 0;
//Identifying the greates size among the sublists
this.maxSublistSize = nestedList.stream().map(list -> list.size()).max(Integer::compareTo).orElse(0);
}
@Override
public boolean hasNext() {
//If the sublist cursor hasn't exceeded the last "column" then there are further elements to iterate (worst case scenario: only the current element)
return subListCur < maxSublistSize;
}
@Override
public Integer next() {
//If the last column has been exceeded (no further elements to iterate) then no value is returned
if (subListCur == maxSublistSize) {
return null;
}
//Saving the current value to return
Integer value = nestedList.get(listCur).get(subListCur);
//Incrementing the outer list cursor to point to the next "row" (matrix visualization)
if (listCur < nestedList.size() - 1) {
listCur++;
} else {
//Incrementing the sublist cursors to point to the next column and resetting the "row" index (matrix visualization)
subListCur++;
listCur = 0;
}
// In case there are still elements left and the current cursors do not point to an existing element (sublist cursor greater than the sublist's size)
// then these "empty spots" are skipped as long as the last column hasn't been exceeded or the next element hasn't been met
while (subListCur < maxSublistSize && subListCur >= nestedList.get(listCur).size()) {
if (listCur < nestedList.size() - 1) {
listCur++;
} else {
subListCur++;
listCur = 0;
}
}
return value;
}
}
public class Main {
public static void main(String[] args) {
//Added extra empty lists to create more "empty sposts"
List<List<Integer>> nestedList = new ArrayList<>(List.of(List.of(1, 2, 3), List.of(4, 5), List.of(6), List.of(), List.of(7, 8, 9), List.of(), List.of()));
System.out.println("------------ Iterator ------------");
CustomListIteratorVert custIt = new CustomListIteratorVert(nestedList);
while (custIt.hasNext()) {
System.out.println(custIt.next());
}
System.out.println("\n\n------------ Flattened List foreach loop ------------");
List<Integer> listFlattenedFor = new ArrayList<>();
for (List<Integer> sublist : nestedList) {
listFlattenedFor.addAll(sublist);
}
listFlattenedFor.forEach(i -> System.out.println(i));
System.out.println("\n\n------------ Flattened List Stream ------------");
List<Integer> listFlattenedStream = new ArrayList<>();
nestedList.stream().forEach(list -> listFlattenedStream.addAll(list));
listFlattenedFor.forEach(i -> System.out.println(i));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.