通用遍历模式
遍历
链表遍历
- 如果底层基于数组,比如
ArrayList
,使用下标索引遍历性能最好,使用迭代器也能接受 - 如果底层基于链表,比如
LinkedList
,使用迭代器遍历性能最好,但是使用下标索引不可接受
集合操作类中使用了RamdomAccess
作为区分选择遍历模式
1 | public static <T> void fill(List<? super T> list, T obj) { |
Java5提供了通用的遍历模式foreach
,无需知道内部结构,直接遍历
Iterable
foreach
遍历集合实际是基于Iterable
接口,集合类都实现了这一接口
自定义类只要实现这个接口也可以用foreach循环
1 | public interface Collection<E> extends Iterable<E> { |
遍历集合时,等价于在循环中使用迭代器
1 | List<String> list = Arrays.asList("foo","bar"); |
Iterable
代表可以被遍历的能力,可返回具体的迭代器
1 | public interface Iterable<T> { |
Iterator
Iterator
代表具体的遍历实现逻辑,核心方法只有两个hasNext
判断还有没有,next
取下一个数据
如果实现支持,还可以遍历时进行删除
1 | public interface Iterator<E> { |
迭代特性
- 数量无关,不能提前知道总量有多少
- 不可逆,如果没有特殊实现,
Iterator
一次性使用,前进后不能倒退。如果需要多次遍历,使用Iterable
,可再生出新的迭代器
扩展接口ListIterator
专为list设计的迭代器
- 支持双向遍历
- 支持获取索引
- 支持增删改操作
1 | public interface ListIterator<E> extends Iterator<E> { |
扩展
可以使用装饰器模式改变迭代器的行为,在外部看来还是普通的迭代器,感知不到变化
动态转换类型
Guava
扩展next
,获取数据后进行转换
1 | Iterator<Object> newIterator = Iterators.transform(iterator, o -> o.toString().length()); |
循环
Guava
扩展hasNext
逻辑,发现遍历结束就重新开始遍历
1 | Iterator<Object> newIterator = Iterators.cycle(iterator); |
拼接
Guava
将多个迭代器保存起来,扩展hasNext
逻辑,发现上一个遍历完成就开始遍历下一个
1 | Iterator<Object> newIterator = Iterators.concat(iterator1,iterator2); |
过滤
Guava
扩展hasNext
,调用时内部会不断执行next
取数据,进行判断,直到找到满足条件的数据保存起来
1 | Iterator<Object> newIterator = Iterators.filter(iterator, o -> o.toString().length() == 3); |
数量限制
Guava
扩展hasNext
,达到数量限制后直接返回false
1 | Iterator<Object> newIterator = Iterators.limit(iterator,10); |
Enumeration
早期Java的迭代接口,Vector
和HashTable
实现此接口
Iterator
方法名更简洁,并且有额外的remove
方法, 因此这个接口已被取代,只作为遗留代码
1 | public interface Enumeration<E> { |
一分也是爱~
版权声明
This site by Linest is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由Linest创作并维护的博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。