亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 Iterable<T> 中以最有效的方式獲取特定位置的元素?

如何在 Iterable<T> 中以最有效的方式獲取特定位置的元素?

開心每一天1111 2023-03-09 17:21:33
我需要在特定位置獲取一個元素,Iterable<MyType>以免遍歷所有元素,Iterable<MyType>因為我知道所需元素位于哪個位置(就我而言,遍歷所有元素將花費 O(n) 時間,另一方面訪問特定的將花費 O(1) 時間)。這必須是最后一個之前的元素。但我找不到辦法做到這一點。public interface Iterable<T>,顯然,沒有方法來訪問任意位置的元素。我嘗試投射Iterable<MyType>到,List<MyType>但投射在運行時失敗了ClassCastException。所以我不能使用ListIterator<E>, simpleList.get(E e)或一些自定義Function<T, U>來向后遍歷元素或獲取這個元素(我打算做的這些事情)。我當前的代碼// list.getItems() returns Iterable<MyType>// I know that element I am looking for is at (iterable.size - 2) position        for(MyType item : list.getItems()) {            if (item.convertToText().matches(targetElementRegex)) {                Pattern pattern = Pattern.compile(targetElementRegex);                Matcher matcher = pattern.matcher(item.convertToText());                if (matcher.find()) {                    return Optional.of(Integer.parseInt(matcher.group(1)));                }            }}正如您目前看到的,我只是循環遍歷所有元素,Iterable<T>直到到達目標元素,盡管我知道我正在尋找的目標元素位于哪個位置。我想在Iterable<MyType>.我想找出最有效的方法來做到這一點(或者至少是比我當前的解決方案更好的方法)。UPD:list是來自第三方庫的類的實例,我沒有寫,我也可以在類getItems()中添加新的東西。list
查看完整描述

4 回答

?
牧羊人nacy

TA貢獻1862條經驗 獲得超7個贊

Iterable沒有為您提供在給定位置提取元素的方法,這是設計使然。集合框架包含更多專門的類來處理具有O(1)元素訪問的順序集合。這些是各種眾所周知的列表實現,尤其是那些實現RandomAccess接口的。

如您所見,選擇集合接口會產生很大的不同,尤其是在涉及O(xxx)符號方面。這是多功能性和性能之間的一種權衡。通用接口為Iterable您提供了最廣泛的適用輸入集,但您只能獲得RandomAccess集合的性能。

如果您要使用的所有輸入都是RandomAccess集合(ArrayList實現它),則沒有理由將它們作為Iterable. 如果不是這種情況,您可以在運行時檢查此條件并選擇最有效的算法。


查看完整回答
反對 回復 2023-03-09
?
慕絲7291255

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);


查看完整回答
反對 回復 2023-03-09
?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

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



查看完整回答
反對 回復 2023-03-09
?
慕工程0101907

TA貢獻1887條經驗 獲得超5個贊

如果您只想要倒數第二個位置,為什么不在進入循環之前用列表索引那個位置呢?而不是 list.getItems(),嘗試 list.getItem(list.getItemCount()-2)



查看完整回答
反對 回復 2023-03-09
  • 4 回答
  • 0 關注
  • 240 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號