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)
添加回答
举报