Почему класс String в Java не реализует Iterable? - PullRequest
44 голосов
/ 05 мая 2010

Многие классы инфраструктуры Java реализуют Iterable, однако String - нет. Имеет смысл перебирать символы в String, так же как можно перебирать элементы в обычном массиве

Есть ли причина, по которой String не реализует Iterable?

Ответы [ 7 ]

24 голосов
/ 05 мая 2010

Там действительно нет хорошего ответа. Итератор в Java специально применяется к коллекции дискретных элементов (объектов). Можно подумать, что String, который реализует CharSequence, должен быть «набором» дискретных символов. Вместо этого он рассматривается как единое целое, состоящее из символов.

В Java кажется, что итераторы действительно применяются только к коллекциям, а не к строке. Нет причин, почему это так (насколько я могу судить - вам, вероятно, придется поговорить с Гослингом или авторами 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).

EDIT

Чтобы уточнить на основе комментариев к этому ответу. Я пытаюсь объяснить возможное обоснование , почему итератор в String отсутствует. Я не пытаюсь сказать, что это невозможно; действительно, я думаю, что для CharSequence имеет смысл реализовать Iterable.

String обеспечивает CharSequence, что, хотя бы концептуально, отличается от String. String обычно рассматривается как единое целое, тогда как CharSequence - это как раз последовательность символов. Было бы целесообразно иметь итератор для последовательности символов (то есть для CharSequence), а не просто для самого String.

Как правильно заметил Foxfire в комментариях, String реализует интерфейс CharSequence, поэтому для типов String - это CharSequence. С семантической точки зрения мне кажется, что это две разные вещи - я, вероятно, здесь педантичен, но когда я думаю о String, я обычно думаю о нем как об одной сущности, которая, как оказалось, состоит из символов. Рассмотрим разницу между последовательностью цифр 1, 2, 3, 4 и числом 1234. Теперь рассмотрим разницу между строкой abcd и последовательностью символов a, b, c, d. Я пытаюсь указать на эту разницу.

По моему мнению, спросить, почему у String нет итератора, все равно, что спросить, почему у Integer нет итератора, чтобы вы могли перебирать отдельные цифры.

12 голосов
/ 05 мая 2010

Причина проста: строковый класс намного старше, чем Iterable.

И, очевидно, никто никогда не хотел добавлять интерфейс в String (что несколько странно, потому что он реализует CharSequence, который основан на точно такой же идее).

Однако это было бы несколько несовершенно, потому что Iterable возвращает объект . Так что придется оборачивать каждый возвращенный символ.

Редактировать: так же, как сравнение: .Net поддерживает перечисление для String, однако в .Net Iterable также работает с нативными типами, поэтому нет необходимости в переносе, как в Java.

10 голосов
/ 06 мая 2010

Как бы то ни было, мой коллега Джош Блох очень хочет добавить эту функцию в Java 7:

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

и

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

Это был бы самый простой способ зацикливания символов и логических символов (кодовых точек). Для этого не потребуется String реализовать Iterable, что заставит бокс произойти.

Без этой языковой возможности не будет действительно хорошего ответа на эту проблему. И он кажется очень оптимистичным, что он может добиться этого, но я не уверен.

4 голосов
/ 26 мая 2010

Они просто забыли это сделать.

2 голосов
/ 04 июня 2010

Одной из основных причин того, что String реализует Iterable, является включение простого цикла for (each), как упоминалось выше. Таким образом, причиной того, что String не может быть реализована в Iterable, может быть неэффективность, присущая наивной реализации, поскольку она требует упаковки результата. Однако, если реализация получающегося итератора (возвращаемого String.iterator ()) является окончательной, компилятор может выполнить специальный случай и сгенерировать байт-код, свободный от упаковки / распаковки.

0 голосов
/ 05 мая 2010

Iterable чего? Iterable<Integer> будет наиболее целесообразно, когда каждый элемент представляет кодовую точку Unicode. Даже Iterable<Character> будет медленным и бессмысленным, когда у нас будет toCharArray.

0 голосов
/ 05 мая 2010

Если вы действительно заинтересованы в повторении здесь:

String str = "StackOverflow";

for (char c: str.toCharArray()){
     //here you go
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...