web-dev-qa-db-ja.com

JavaのStringクラスがIterableを実装しないのはなぜですか?

多くのJavaフレームワーククラスはIterableを実装しますが、Stringは実装しません。Stringの文字を1つと同じように繰り返すのは理にかなっています。通常の配列内のアイテムを反復処理できます。

StringIterableを実装しない理由はありますか?

45
user333335

本当に良い答えはありません。 Javaのイテレータは、個別のアイテム(オブジェクト)のコレクションに特に適用されます。Stringを実装するCharSequenceは、「」である必要があります。個別の文字のコレクション」。代わりに、文字で構成される単一のエンティティとして扱われます。

Javaでは、イテレータは実際にはコレクションにのみ適用され、文字列には適用されないようです。これがこのようになっている理由はありません(私が知る限り、おそらくGoslingまたはAPIライターと話をする必要があります)。それは慣例または設計上の決定のようです。確かに、CharSequenceIterableを実装するのを妨げるものは何もありません

そうは言っても、次のように文字列内の文字を繰り返すことができます。

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)です。

[〜#〜]編集[〜#〜]

この回答へのコメントに基づいて明確にする。 Stringにイテレータがない理由について考えられる理論的根拠を説明しようとしています。私はそれが不可能だと言っているのではありません。確かに、CharSequenceIterableを実装することは理にかなっていると思います。

StringCharSequenceを提供します。これは、概念的にのみ、Stringとは異なります。 Stringは通常、単一のエンティティと見なされますが、CharSequenceはまさにそれです:文字のシーケンス。 CharSequence自体だけでなく、一連の文字(つまり、String)にイテレータを配置することは理にかなっています。

Foxfireがコメントで正しく指摘しているように、StringCharSequenceインターフェースを実装しているため、タイプ的には、StringCharSequenceです。意味的には、これらは2つの別個のものであるように思われます。おそらくここでは衒学者ですが、Stringについて考えるとき、通常、文字で構成される単一のエンティティと考えます。数字のシーケンス1, 2, 3, 4と数字の1234の違いを考慮してください。次に、文字列abcdと文字列a, b, c, dの違いについて考えてみましょう。私はこの違いを指摘しようとしています。

私の意見では、Stringにイテレータがない理由を尋ねるのは、個々の桁を反復できるようにIntegerにイテレータがない理由を尋ねるようなものです。

25
Vivin Paliath

理由は単純です。文字列クラスはIterableよりはるかに古いです。

そして明らかに、Stringにインターフェースを追加したいと思ったことはありません(まったく同じアイデアに基づいたCharSequenceを実装しているため、これはやや奇妙です)。

ただし、それはIterableがオブジェクトを返すため、やや不適合になります。したがって、返されたすべての文字をラップする必要があります。

編集:比較と同じように:.Netは文字列での列挙をサポートしますが、.NetではIterableはネイティブ型でも機能するため、Javaで必要とされるようなラッピングは必要ありません。

13
Foxfire

私の同僚のJoshBlochは、この機能をJava 7:

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

そして

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

これは、文字や論理文字(コードポイント)をループする最も簡単な方法です。 StringIterableを実装させる必要はありません。これにより、ボクシングが強制的に発生します。

その言語機能がなければ、この問題に対する本当に良い答えはありません。そして、彼はこれを実現できると非常に楽観的だと思いますが、私にはわかりません。

11

彼らは単にそうするのを忘れていました。

4
akuhn

StringをIterableに実装する主な理由の1つは、前述のように、単純なfor(each)ループを有効にすることです。したがって、StringをIterableに実装しない理由は、結果をボックス化する必要があるため、ナイーブな実装に固有の非効率性である可能性があります。ただし、結果のイテレータ(String.iterator()によって返される)の実装が最終的な場合、コンパイラはそれを特殊なケースに分けて、ボックス化/ボックス化解除のないバイトコードを生成できます。

ここでの反復に本当に興味がある場合:

String str = "StackOverflow";

for (char c: str.toCharArray()){
     //here you go
}
1
medopal

Iterable何ですか? Iterable<Integer>が最も理にかなっており、各要素はUnicodeコードポイントを表します。 toCharArrayがあると、Iterable<Character>でさえ遅く、無意味になります。