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

use*_*335 45 java string iterable

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

有没有理由String不实施Iterable

Viv*_*ath 25

真的没有一个好的答案.Java中的迭代器特别适用于离散项(对象)的集合.你可能会认为,一个String,它实现了CharSequence,应该是一个离散字符"收藏".相反,它被视为恰好由字符组成的单个实体.

在Java中,似乎迭代器只是真正应用于集合而不是字符串.没有理由这样的方式(我可以告诉你 - 你可能不得不与Gosling或API编写者交谈); 它似乎是惯例或设计决定.实际上,没有什么可以阻止 CharSequence实施Iterable.

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

for (int i = 0; i < str.length(); i++) {
  System.out.println(str.charAt(i));
}
Run Code Online (Sandbox Code Playgroud)

要么:

for(char c : str.toCharArray()) {
  System.out.println(c);
}
Run Code Online (Sandbox Code Playgroud)

要么:

"Java 8".chars().forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

另请注意,您无法修改String的字符,因为字符串是不可变的.String的可变伴侣是StringBuilder(或旧的StringBuffer).

编辑

根据对此答案的评论澄清.我试图解释一个可能的理由,为什么没有迭代器String.我并不想说这是不可能的; 事实上,我认为CharSequence实施是有意义的Iterable.

String提供CharSequence,如果仅在概念上,与a不同String.A String通常被认为是单个实体,而CharSequence恰恰是:一系列字符.在一系列字符(即on CharSequence)上有一个迭代器是有意义的,但不是简单地在它String自身上.

正如Foxfire在评论中正确指出的那样,String实现了CharSequence界面,所以类型方面,a String是一个CharSequence.在语义上,在我看来,它们是两个独立的东西 - 我可能在这里迂腐,但是当我想到一个时,String我通常认为它是一个恰好由字符组成的单个实体.考虑的数字序列之间的差异1, 2, 3, 4和数量1234.现在考虑字符串abcd和字符序列之间的区别a, b, c, d.我试图指出这种差异.

在我看来,问为什么String没有迭代器就像问为什么Integer没有迭代器,这样你就可以迭代各个数字.

  • "字符串实际上不是离散字符的"集合"." 好吧.事实上,它甚至实现了CharSequence,这正是:离散字符的有序集合! (8认同)
  • 你可以用C#做​​'foreach(char c in s)`,真漂亮! (6认同)
  • 当然,将字符串视为字母集合并非完全没有先例,并且在"有道理"的情况下对其进行争辩似乎有些虚假. (4认同)
  • @Vivin:那么imho你应该试着回答原来的问题:"为什么CharSequence没有实现Iterable".(当然,这在技术上仍然意味着"为什么String不能实现Iterable") (2认同)

Fox*_*ire 13

原因很简单:字符串类比Iterable早得多.

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

然而,它会有点不完美,因为Iterable返回一个对象.所以它必须包裹每个Char返回.

编辑:正如比较:.Net确实支持对String进行枚举,但在.Net中,Iterable也适用于本机类型,因此不需要包装,因为它在Java中是必需的.

  • 我看不到将`Iterable`(或任何类型)添加到`String`是一个重大变化.这不像你可以继承`String`(感谢上帝). (2认同)
  • 任何像破坏的代码都应该被打破.我认为我很安全地说这不是一个考虑的原因. (2认同)

Kev*_*ion 10

值得一提的是,我的同事Josh Bloch强烈希望将此功能添加到Java 7中:

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

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

这将是循环字符和​​逻辑字符(代码点)的最简单方法.它不需要制造String工具Iterable,这将迫使拳击发生.

没有这种语言功能,对这个问题不会有一个非常好的答案.他似乎非常乐观地认为他可以做到这一点,但我不确定.