多くの Java フレームワーク クラスは を実装していますがIterable
、実装String
していません。String
通常の配列内のアイテムを反復できるのと同じように、 a 内の文字を反復することは理にかなっています。
String
実装しない理由はありますIterable
か?
本当に良い答えはありません。Java の反復子は、個別の項目 (オブジェクト) のコレクションに特に適用されます。String
を実装するCharSequence
は、個別の文字の「コレクション」であるべきだと考えるでしょう。代わりに、文字で構成される単一のエンティティとして扱われます。
Java では、イテレータは実際にはコレクションにのみ適用され、文字列には適用されないようです。このようになる理由はありません (私が知る限り、おそらく Gosling または API ライターと話をする必要があるでしょう)。それは慣習または設計上の決定のようです。実際、実装を妨げる ものは何もありません。CharSequence
Iterable
つまり、次のように文字列内の文字を反復処理できます。
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 の変更可能なコンパニオンは StringBuilder (または古い StringBuffer) です。
編集
この回答に対するコメントに基づいて明確にする。にIterator がない理由について、考えられる理論的根拠を説明しようとしていString
ます。不可能だと言っているわけではありません。CharSequence
確かに、実装するのは理にかなっていると思いますIterable
。
String
を提供しますCharSequence
。これは、概念的にのみ、 とは異なりString
ます。AString
は通常、単一のエンティティと考えられていますが、 A はCharSequence
まさにそれであり、一連の文字です。文字のシーケンス (つまり、 on CharSequence
) にイテレータを使用することは理にかなっていますが、単にString
それ自体にではありません。
Foxfire がコメントで正しく指摘しているようにString
、インターフェイスを実装しているCharSequence
ため、型的には aString
は aCharSequence
です。意味的には、それらは 2 つの別個のものであるように思われます。ここではおそらく衒学的に説明していますが、私が を考えるときは、String
通常、たまたま複数の文字で構成される単一のエンティティとして考えます。1, 2, 3, 4
数字の並びと数字の違いを考えてみましょう1234
。abcd
ここで、文字列と文字列の違いを考えてみましょうa, b, c, d
。私はこの違いを指摘しようとしています。
私の意見では、イテレータがない理由を尋ねることは、個々の数字を反復処理できるようにイテレータがないString
理由を尋ねるようなものです。Integer
理由は簡単です。文字列クラスは Iterable よりもずっと古いからです。
そして明らかに、誰も String にインターフェースを追加したいとは思っていませんでした (まったく同じ考えに基づいた CharSequence を実装しているため、これは少し奇妙です)。
ただし、 Iterable は object を返すため、多少パフォーマンスが低下します。したがって、返されるすべての Char をラップする必要があります。
編集:ちょうど比較: .Net は文字列の列挙をサポートしていますが、.Net では Iterable はネイティブ型でも機能するため、Java で必要なラッピングは必要ありません。
私の同僚である Josh Bloch は、この機能を Java 7 に追加することを強く望んでいます。
for (char c : aString) { ... }
と
for (int codePoint : aString) { ... }
これは、文字と論理文字 (コード ポイント) をループする最も簡単な方法です。ボクシングを強制的に行うString
implementを作成する必要はありません。Iterable
その言語機能がなければ、この問題に対する本当に良い答えはありません。そして、彼はこれを実現できると非常に楽観的に見えますが、私には確信が持てません。
彼らは単にそうするのを忘れていました。
String を Iterable に実装する主な理由の 1 つは、前述の単純な for(each) ループを有効にすることです。したがって、 String を Iterable に実装しない理由は、結果をボックス化する必要があるため、ナイーブな実装に固有の非効率性である可能性があります。ただし、結果のイテレーター (String.iterator() によって返される) の実装が最終的なものである場合、コンパイラーはそれを特殊ケースにして、ボックス化/ボックス化解除のないバイトコードを生成できます。
ここで反復することに本当に関心がある場合:
String str = "StackOverflow";
for (char c: str.toCharArray()){
//here you go
}
Iterable
なにかの?Iterable<Integer>
各要素が Unicode コードポイントを表す場合、最も理にかなっています。を持っていてもIterable<Character>
遅くて無意味toCharArray
です。