Подтвердить что ты не робот

Почему класс String в Java не реализует Iterable?

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

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

4b9b3361

Ответ 1

На самом деле нет хорошего ответа. Итератор в 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).

ИЗМЕНИТЬ

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

и

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

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

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

Ответ 4

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

Ответ 5

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

String str = "StackOverflow";

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

Ответ 6

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

Ответ 7

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