为什么Java中的String类没有实现Iterable?

许多Java框架类实现Iterable ,但String不。 迭代String字符是有意义的,就像迭代常规数组中的项一样。

String没有实现Iterable的原因吗?

真的没有一个好的答案。 Java中的迭代器特别适用于离散项目(对象)的集合。 你会认为一个实现CharSequenceString应该是离散字符的“集合”。 相反,它被视为恰好由字符组成的单个实体。

在Java中,似乎迭代器只适用于集合而不是string。 没有理由为什么会这样(接近我可以告诉 – 你可能必须与高斯林或API作家谈话); 它似乎是约定或devise决定。 事实上,没有什么能够阻止 CharSequence实现Iterable

也就是说,你可以迭代string中的字符,如下所示:

 for (int i = 0; i < str.length(); i++) { System.out.println(str.charAt(i)); } 

要么:

 for(char c : str.toCharArray()) { System.out.println(c); } 

要么:

 "Java 8".chars().forEach(System.out::println); 

另外请注意,您不能修改string的字符,因为string是不可变的。 String的可变伴侣是StringBuilder(或更老的StringBuffer)。

编辑

根据对这个答案的评论来澄清。 我试图解释为什么在String上没有Iterator 可能的基本原理 。 我不是想说这是不可能的; 实际上我认为CharSequence实现Iterable有意义的。

String提供了CharSequence ,它只是在概念上与String不同。 一个String通常被认为是一个单一的实体,而CharSequence恰恰是:一个字符序列。 在字符序列上(即在CharSequence )有一个迭代器是有意义的,但不能简单地在String本身上。

正如Foxfire在评论中正确地指出的那样, String实现了CharSequence接口,所以type-wise是一个CharSequence 。 在语义上,在我看来,它们是两个单独的东西 – 我可能在这里是迂腐的,但是当我想到一个String我通常把它看作是一个单一的实体,恰好由字符组成。 考虑数字1, 2, 3, 4和数字1234之间的区别。 现在考虑stringabcd和字符序列a, b, c, d之间的区别。 我试图指出这种差异。

在我看来,问为什么String没有一个迭代器就像问为什么Integer没有一个迭代器,以便您可以遍历个别数字。

原因很简单:string类比Iterable旧。

显然没有人想把接口添加到String(这有点奇怪,因为它实现了基于完全相同的想法的CharSequence)。

然而,这将是有点不足,因为Iterable返回一个对象 。 所以它将不得不包裹每个字符返回。

编辑:就像比较:.Net不支持在string上枚举,但是在.net中Iterable也可以在本地types上工作,所以没有必要的包装,因为它需要在Java中。

值得一提的是,我的同事Josh Bloch强烈希望将这个特性添加到Java 7中:

for (char c : aString) { ... }

for (int codePoint : aString) { ... }

这将是循环字符和​​逻辑字符(代码点)的最简单的方法。 它不需要使String实现Iterable ,这将迫使Boxing发生。

没有这种语言function,这个问题就不会有很好的答案。 他似乎很乐观,他可以得到这个发生,但我不知道。

他们只是忘了这么做。

如果你真的有兴趣在这里迭代:

 String str = "StackOverflow"; for (char c: str.toCharArray()){ //here you go } 

使String实现为Iterable的主要原因之一是为了简化(each)循环,如上所述。 所以,没有把String实现为Iterable的原因可能是天真实现的内在低效率,因为它需要装箱结果。 但是,如果由String.iterator()返回的结果迭代器的实现是最终的,编译器可以对它进行特殊处理并生成无装箱/拆箱的字节码。

什么是可Iterable的? Iterable<Integer>是最有意义的,每个元素代表一个Unicode代码点。 甚至当我们需要toCharArray时候, Iterable<Character>也是缓慢而毫无意义的。