2010-05-05 2 views
37

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

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

+1

Нужна проблема для итерации массива символов Array? (strInput.ToCharArray) –

+4

Tim: Строка # toCharArray создает массив с копией символов String. Даже если он работает, он накладывает ненужные накладные расходы, чтобы перебирать символы. – jarnbjo

+1

@jambjo 'Iterator ' будет меньше над головой ??? –

ответ

17

На самом деле нет хорошего ответа. Итератор в 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. A String обычно рассматривается как единый объект, тогда как CharSequence - это то, что: последовательность символов. Было бы целесообразно иметь итератор последовательности символов (т. Е. На CharSequence), но не просто на самом String.

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

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

+4

Конечно, обработка строки в виде набора букв не является целиком без прецедента, а аргументировать ее в случае «имеет смысл» немного паразитный. – Svend

+0

@Svend это правда - я был в затруднении для слов - я думаю, что хотел сказать «это не имеет смысла в некоторых случаях» или даже «это не имеет смысла в большинстве случаев», учитывая то, что итераторы действительно , Я отредактирую свой ответ. –

+7

«Строка на самом деле не является« коллекцией »дискретных символов». Хорошо. На самом деле он даже реализует CharSequence, что и есть: коллекция Orderd дискретных символов! – Foxfire

1

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

String str = "StackOverflow"; 

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

-1 Извините, но я не вижу, что этот ответ имеет отношение к заданному вопросу. – jarnbjo

+3

Проблема может заключаться в том, что toCharArray создает новый массив. Так что это ОЧЕНЬ неэффективно. – Foxfire

+0

@Helper: Строка неизменна. Однако возвращенный массив не является. И изменение Массив не должно влиять на String. Поэтому он делает полную копию. – Foxfire

12

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

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

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

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

+0

«Добавление класса Iterable в класс String делает его неустойчивым», имеет смысл; но никто не добавил Itreable в класс String только потому, что он был старым, кажется немного странным.не могли бы вы объяснить еще? – phoenix24

+0

Строка существовала задолго до Iterable. Поэтому вам придется добавить интерфейс позже. В то время как это возможно, это может быть - в некоторых случаях с углами - быть изменением. И принимая во внимание, как часто используется String, это может быть что-то считающееся рискованным. Это просто догадки. Я не знаю, действительно ли эти соображения повлияли на это решение. Но это кажется наиболее вероятным. – Foxfire

+1

Я не вижу добавления 'Iterable' (или любого типа) в' String' как нарушение. Это не похоже на подкласс 'String' (слава богу). –

0

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

10

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

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

и

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

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

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

+5

Вы работаете с Джошуа Блохом? Милая! –

+0

Слишком плохо, что не попал в проектную монету Java 7. – akuhn

+0

Если они когда-нибудь планировали это сделать, убедитесь, что они работают для любых объектов, наследующих 'CharSequence', а не только для' String'. –

4

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

+0

У вас есть доказательства этого утверждения? Мне кажется более вероятным, что это связано с тем, что String предшествует интерфейсу Iterable (строки, предположительно датированные Java 1.0, Iterable датируется Java 1.5), и как только спецификаторы языка привыкли не рассматривать String как одну из коллекций, они продолжали относиться к этому так. – Anomaly

2

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

Смежные вопросы