java 迭代器排序_Java迭代器 - 大熊猫的个人页面 - OSCHINA - 中文开源技术交流社区...

通过使用迭代器,我们可以很轻松地遍历一个对象集合。

Java的迭代器接口为Iterator,可通过Iterable的iterator()方法获取。

Connection接口继承了Iterable接口,因此所有Connection的子类都可使用迭代器进行遍历。

Iterable接口仅有3个方法:

Iterator iterator();

default void forEach(Consumer super T> action)

default Spliterator spliterator()

iterator()

此方法返回一个Iterator对象,Iterator中有4个方法:

boolean hasNext();           // 判断迭代器中是否还有元素

E next();                            // 获取下一个元素

default void remove();     // 删除最近一次从迭代器返回的元素,此方法在每次调用next()后只能调用一次

default void forEachRemaining(Consumer super E> action);   // 对剩余元素进行遍历

我们通过以下代码来分析上述4个方法:

public static void run() {

List list = new ArrayList<>();

for (int i = 0; i < 5; i++) {

list.add("" + i);

}

Iterator iterator = list.iterator();

while (iterator.hasNext()) { // [1]

String str = iterator.next(); // [2]

Log.d(TAG, "run remove:" + str);

iterator.remove(); // [3]

// iterator.remove(); // [4]

iterator.next(); // [5]

iterator.forEachRemaining(new Consumer() { // [6]

@Override

public void accept(String s) {

Log.d(TAG, "forEachRemaining:" + s);

}

});

}

list中保存了“1”~“4”共5个字符串,程序运行结果为:

D IterableTest:run remove:0

D IterableTest:forEachRemaining:2

D IterableTest:forEachRemaining:3

D IterableTest:forEachRemaining:4

[1]:判断是否有下一个元素,第一次执行到此处是肯定是有下一个元素的,于是进入while循环。

[2]:获取下一个元素,第一次进入while循环获取到的是字符串“0”。

[3]:删除最近一次获取到的元素,即[2]中取得的元素。

[4]:连续执行两次删除操作会报异常。

[5]:再次获取下一个元素,第一次进入while循环获取到的是字符串“1”。

[6]:对剩余元素进行遍历,由于前两个元素已被取出,因此仅对剩余的“2”~“4”进行遍历,且遍历完成后,第二次while判断hasNext()时,由于已经遍历完,因此返回false,退出while循环。

去掉[4]的注释后,程序运行报以下异常:

java.lang.IllegalStateException

at java.base/java.util.ArrayList$Itr.remove(ArrayList.java:976)

at com.xjn.javatest.IteratorTest.run(IteratorTest.java:22)

at test.com.xjn.javatest.IteratorTestTest.testRun(IteratorTestTest.java:32)

......

forEach(Consumer super T> action)

此方法实际上就是使用了增强型for循环,其源码如下:

default void forEach(Consumer super T> action) {

Objects.requireNonNull(action);

for (T t : this) {

action.accept(t);

}

}

通过以下代码进行测试:

public static void forEachTest() {

List list = new ArrayList<>();

for (int i = 0; i < 3; i++) {

list.add("" + i);

}

list.forEach(element -> Log.d(TAG, "forEachTest:" + element)); // [1]

}

[1]:这里使用了lamba表达式,上例中的Iterator.forEachRemaining()同样支持这种写法。

运行结果为:

D IterableTest:forEachTest:0

D IterableTest:forEachTest:1

D IterableTest:forEachTest:2

spliterator()

可分割的迭代器(Splitable Iterator)。

分割元素,并返回分割出来的元素对应的Spliterator对象,即可分割的迭代器(Splitable Iterator)。

Spliterator包含的方法有:

boolean tryAdvance(Consumer super T> action);                    // 如果有剩余元素,则在此元素上执行对应动作,并返回true;否则返回false。

default void forEachRemaining(Consumer super T> action);   // 遍历剩余所有元素

Spliterator trySplit();                                                               // 从当前Spliterator分割一部分出来并返回

long estimateSize();                                                                       // 返回剩余元素个数

default long getExactSizeIfKnown();                                              // 若有特征SIZED,则返回estimateSize(),否则返回-1

int characteristics();                                                                        // 获取特征

default boolean hasCharacteristics(int characteristics);                 // 判断是否存在指定特征

default Comparator super T> getComparator();                       // 如果元素是通过Comparator排序,则返回Comparator;如果是自然排序,返回null;否则抛出异常IllegalStateException。

以下例进行说明:

public static void spliteratorTest() {

List list = new ArrayList<>();

for (int i = 0; i < 10; i++) {

list.add("" + i);

}

Spliterator split = list.spliterator();

split.tryAdvance(s -> Log.d(TAG, "spliteratorTest:" + s)); // [1]

try {

Log.d(TAG, "spliteratorTest Comparator:" + split.getComparator()); // [2]

} catch (IllegalStateException e) {

Log.e(TAG, "spliteratorTest Comparator e:" + e); // [3]

}

Log.d(TAG, "spliteratorTest ExactSizeIfKnown:" + split.getExactSizeIfKnown()); // [4]

Log.d(TAG, "spliteratorTest Size:" + split.estimateSize()); // [5]

Log.d(TAG, "spliteratorTest characteristics:" + String.format("0x%x", split.characteristics())); // [6]

Spliterator split1 = split.trySplit(); // [7]

split.forEachRemaining(s -> Log.d(TAG, "spliteratorTest split:" + s)); // [8]

split1.forEachRemaining(s -> Log.d(TAG, "spliteratorTest split1:" + s)); // [9]

}

[1]:通过tryAdvance()获取一个元素。

[2]~[3]:获取Comparator,由于ArrayList没有排序,因此抛出异常。

[4]~[6]:获取特性、剩余元素个数等

[7]:将Spliterator进行分割

[8]~[9]:分别遍历分割后的2个Spliterator剩余的所有元素。

输出结果为:

D IterableTest:spliteratorTest:0

E IterableTest:spliteratorTest Comparator e:java.lang.IllegalStateException

D IterableTest:spliteratorTest ExactSizeIfKnown:9

D IterableTest:spliteratorTest Size:9

D IterableTest:spliteratorTest characteristics:0x4050

D IterableTest:spliteratorTest split:5

D IterableTest:spliteratorTest split:6

D IterableTest:spliteratorTest split:7

D IterableTest:spliteratorTest split:8

D IterableTest:spliteratorTest split:9

D IterableTest:spliteratorTest split1:1

D IterableTest:spliteratorTest split1:2

D IterableTest:spliteratorTest split1:3

D IterableTest:spliteratorTest split1:4

特征有以下可选值,可以是多个值的组合:

DISTINCT   = 0x00000001;         // 元素集合中没有相同的元素

SORTED     = 0x00000004;         // 元素是有序的

ORDERED    = 0x00000010;       // 以为元素定义顺序,trySplit()、tryAdvance()等就按这个顺序进行遍历

SIZED      = 0x00000040;            // 元素个数有限,可返回具体的个数

NONNULL    = 0x00000100;      // 元素不能为null

IMMUTABLE  = 0x00000400;     // 元素不可变,即遍历过程禁止修改(新增、删除、修改)

CONCURRENT = 0x00001000;   // 对元素的修改是线程安全的

SUBSIZED   = 0x00004000;        // 表示由trySplit()分割后的所有Spliterator都具有SIZED和SUBSIZED特征值

问:Iterable与Iterator的关系,为何不直接在Iterable加入迭代接口?

答:Iterable提供了获取迭代器的接口,同时也提供了一个forEach的接口(非迭代方式)。

Iterator则提供了更丰富的迭代方式。

之所以不直接在Iterable中提供Iterator中的迭代接口,是因为有些容器可能会提供多种迭代方式,那么就可以通过返回不同的Iterator实例来实现。

--end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值