2015-03-25 2 views
4

Я вижу четыре альтернативы для преобразования char в Stirng в Java.Быстрое преобразование символов в Java

v = Something.lookup(new String((char)binaryData[idx])); // SORRY! Wrong. 
v = Something.lookup("" + (char)binaryData[idx]); 
v = Something.lookup(String.valueOf((char)binaryData[idx])); 
v = Something.lookup(Character.toString((char)binaryData[idx]))); 

Я думаю, что первое является самым медленным. Второй очень удобен. Я предполагаю, что третий может вернуть ранее созданный экземпляр String, но я не уверен, и документация API не говорит об этом. То же самое относится к четвертому варианту. Это повторное использование экземпляра было бы очень удачным, потому что тогда хэш-поиск мог использовать кеширование hashCode() в String. (Эта функция также не описана в документации API, но многие люди мне сказали.)

Я иду с C++, и я чувствую, что эта информация о недостаточной сложности информации вызывает беспокойство. :-) Правильны ли мои предположения? Есть ли у нас какая-либо официальная документация, в которой объявлены гарантии производительности и объявлены механизмы кэширования?

+5

«Второе очень удобно» - нет, если вы пытаетесь прочитать код, ИМО. В коде используется конкатенация строк и пустая строка, ни одна из которых не является частью того, что вы действительно хотите достичь. 'String.valueOf', IMO - и вы * измерили * любой из них? Знаете ли вы, что это действительно узкое место в вашем коде? Вы пытались определить, кэширует ли значение 'String.valueof' * *? (Это легко понять ...) Предполагая, что 'binaryData' является' byte [] ', вы можете легко построить свой собственный' String [] 'с 256 строками в любом случае, чтобы полностью гарантировать кеширование ... –

+0

3 и 4 являются то же самое .. 4 принудительно вызывает 3 :). Кроме того, у нас нет конструктора String, который принимает один символ (case-1?) – TheLostMind

+0

. Версия 2 будет переводиться компилятором в: создание объекта StringBuilder, к которому затем добавляется ваш символ, наконец, toString() будет вызываться. Так что это довольно дорого. За стоимость v3 или v4 ... вы могли бы взглянуть на источник и посмотреть, что там происходит. – GhostCat

ответ

6

Прежде всего, спецификация Java ничего не знаю о производительности не говорит в отношении этих четырех методов, поэтому результаты могут варьироваться в зависимости от версии JRE и поставщика, которого вы используете.

Если вы используете JRE Oracle, вы можете легко проверить исходный код самостоятельно! В Java 8, выглядит следующим образом:

Учитывая char c с некоторым значением:

  • new String(c) не компилируется. Нет такого конструктора.
  • "" + c выглядит уродливым, громоздким и сложным. Внутри он создает новый пустой StringBuilder и добавляет к нему символ. Затем он создает новый экземпляр String из StringBuilder.
  • Character.toString(c) Делегаты String.valueOf(c).
  • String.valueOf(c) создает новый экземпляр String.

Какой из них использовать?

Наиболее читаемый!

Это String.valueOf(c) или Character.toString(c) с моей точки зрения!

+0

Вы правы! ;) Спасибо, я исправил свой ответ. – isnot2bad

+1

Вы очень хотите обсудить строку intern, чтобы сделать ответ более полным. Бьюсь об заклад, все более низкие 256 символов acii интернированы (кэшированы) при загрузке. –

+1

'' "+ c' немного быстрее из-за специальной оптимизации в JSM HotSpot, но я бы также предпочитал' Character.toString' или 'String.valueOf' для удобства чтения. – apangin

2

Второй, конечно (в теории) медленнее, так как он переводится в

v = Something.lookup(new StringBuilder().append("").append((char)binaryData[idx]).toString()); 

StringBuilder реализованы с использованием char[] инициализируется для хранения 16 значений. Опция StringBuilder поэтому инициализирует char[] размера 16, только для копирования ячеек, которые установлены (только в этом случае в этом случае) в результирующую строку.

String.valueOf (что эквивалентно Character.toString) использует char[] размера 1, а затем непосредственно устанавливает, поддерживающие String «ы char[], тем самым устраняя необходимость копии.

Первый подход не будет компилировать (по крайней мере, не под Java 7), так как нет String конструктора принимать один символ в качестве входных данных: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

+2

"* Второй, конечно, медленнее *" ==> вы были бы удивлены ... – assylias

+0

Я имел в виду, что второй вариант больше работает, и теоретически он должен быть медленнее. – EvenLisle

+0

"* В теории нет никакой разницы между теорией и практикой. На практике есть. *" :-) Бывает, что между тремя вариантами с Hotspot JVM 8 нет заметной разницы. – assylias

1

Первое решение не компилируется. Второе решение внутренне создает строку, вызывающую код, похожий на Character.valueOf(char). Третье решение лучше, чем четвёртая, потому что внутренняя реализация Character.toString(char ch) призыв к String.valueOf

public static String toString(char c) { 
    return String.valueOf(c); 
} 

внутренней реализации третьего String.valueOf(char ch) является

public static String valueOf(char c) { 
    char data[] = {c}; 
    return new String(0, 1, data); 
} 
1

Я иду от C++, и я чувствую, что это отсутствие информации о сложности, вызывающей беспокойство. :-) Правильны ли мои предположения? Есть ли у нас какая-либо официальная документация, в которой объявлены гарантии производительности и объявлены механизмы кэширования?

Чтобы ответить на эту часть вопроса: вообще нет. Вы найдете информацию об асимптотической производительности встроенных коллекций и, возможно, в нескольких других областях, но по большому счету эти проблемы были оставлены на усмотрение виртуальных машин. Вы можете, конечно, всегда смотреть на исходный код, но помните, что есть вещи, которые влияют на производительность, которой у вас нет прямого контроля: JIT-компиляция и сбор мусора являются двумя самыми большими.

Должны ли вы быть обеспокоены этим? Я так не думаю, что Java работает на том основании, что низкоуровневая производительность редко является проблемой, которую разработчик приложения должен заботиться о себе или себе. Это компромисс, и вы можете спорить, хорошо ли это компромисс или нет, но это то, что есть.

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

+0

Я бы добавил больше upvotes, если бы мог, потому что это единственный ответ, который касается второй части вопроса. – Notinlist

+1

@Notinlist Просто небольшое добавление: ваш вопрос (или, вернее, полученные ответы) демонстрирует, как эта политика предоставления очень немногих гарантий реализации работает на практике. '' "+ c' начинался как« плохая привычка », что очень сильно хмурилось, и это было действительно медленно. Но по состоянию на Java 8 этот шаблон, по-видимому, распознается компилятором JIT, который производит для него быстрый код, как и все другие решения. Если бы было больше гарантий по деталям реализации, возможно, это было бы невозможно. – biziclop