4 回答

TA貢獻1862條經驗 獲得超7個贊
Iterable
沒有為您提供在給定位置提取元素的方法,這是設計使然。集合框架包含更多專門的類來處理具有O(1)
元素訪問的順序集合。這些是各種眾所周知的列表實現,尤其是那些實現RandomAccess
接口的。
如您所見,選擇集合接口會產生很大的不同,尤其是在涉及O(xxx)
符號方面。這是多功能性和性能之間的一種權衡。通用接口為Iterable
您提供了最廣泛的適用輸入集,但您只能獲得RandomAccess
集合的性能。
如果您要使用的所有輸入都是RandomAccess
集合(ArrayList
實現它),則沒有理由將它們作為Iterable
. 如果不是這種情況,您可以在運行時檢查此條件并選擇最有效的算法。

TA貢獻1859條經驗 獲得超6個贊
使用 Iterable 接口,您無法獲取特定索引處的元素。所有界面允許您遍歷 Iterable 中的所有項目并觀察其中的內容,僅此而已。您將不得不手動管理當前位置(索引/光標)。一個簡單的解決方案如下:
public static <T> T retrieveItemByIndex(Iterable<T> iterable, int index) {
if (iterable == null || index < 0) {
return null;
}
int cursor = 0;
Iterator<T> iterator = iterable.iterator();
while (cursor < index && iterator.hasNext()) {
iterator.next();
cursor++;
}
return cursor == index && iterator.hasNext() ? iterator.next() : null;
}
如果您不希望此輔助方法使用泛型,只需將其更改為僅適用于您的自定義類型,如:
public MyType retrieveItemByIndex(Iterable<MyType> iterable, int index) {
if (iterable == null || index < 0) {
return null;
}
int cursor = 0;
Iterator<MyType> iterator = iterable.iterator();
while (cursor < index && iterator.hasNext()) {
iterator.next();
cursor++;
}
return cursor == index && iterator.hasNext() ? iterator.next() : null;
}
另一種方法是使用 Stream API(Java 8 及更高版本)。
首先,您必須從 Iterable 中獲取一個流,然后跳過第一個index元素并找到第一個。如果索引超出范圍,將返回默認值。
int index = N - 2;
MyType defaultValue = null;
StreamSupport.stream(iterable.spliterator(), false)
.skip(index)
.findFirst()
.orElse(defaultValue);

TA貢獻1804條經驗 獲得超3個贊
正如 dbl 所提到的,您無法在 Iterable 對象的特定索引處獲取元素。如果您打算將 Iterable 對象轉換為列表,則只需花費相同的時間 (O(n)),再加上獲取目標元素的 O(1)。如果您真的很關心您的 O(n) 時間,我建議您按原樣迭代它直到您的目標元素 (O(n-1))。

TA貢獻1887條經驗 獲得超5個贊
如果您只想要倒數第二個位置,為什么不在進入循環之前用列表索引那個位置呢?而不是 list.getItems(),嘗試 list.getItem(list.getItemCount()-2)
添加回答
舉報