Translate

понеділок, 15 жовтня 2012 р.

Core: String part 2


В продовження попередньої статті про String http://jug-lviv.blogspot.com/2012/10/core-string-part-1.html друга стаття:

Магія String Об'экт/не об'єкт

Хоч String і є об'єктом, але він є immutable і створююється новий об'єкт і референс на старий об'єкт перетираються.
public class StringObject {

    public static void main(String[] args) {
        String val ="object";
        updateString(val);
        System.out.println(val);
    }

    private static void updateString(String val) {
        val ="not object";
        System.out.println(val);
    }
}
На консолі буде виведено:



not object
object
Отже: Не за бувайте, що String хоч і об'єкт але він є іммутабле і значення після передавання в функцію не буде змінюватись!  Приклад pass-by-value.
 

Магія String Concatenation


Всі знають (ну майже всі), що для додавання стрінгів треба використовувати спеціальні класи, але на скільки це критично мало хто задумується...
public class StringPerformance {

    public static void main(String[] args) {
        long start = System.nanoTime();
        badMethod("Test Message", "Watery Lane");
        long duration = System.nanoTime() - start;
        System.out.println("Using Strings took " + duration + "nS");

        start = System.nanoTime();
        StringBufferMethod("Test Message", "Watery Lane");
        duration = System.nanoTime() - start;
        System.out.println("Using StringBuffer took " + duration + "nS");

        start = System.nanoTime();
        StringBuilderMethod("Test Message", "Watery Lane");
        duration = System.nanoTime() - start;
        System.out.println("Using StringBuilder took " + duration + "nS");
    }

    private static String badMethod(String message, String location) {

        String str = "Exception closing down ";

        str += message;
        str += " at ";
        str += location;

        str += " Press any key to exit";

        return str;
    }

    private static String StringBufferMethod(String message, String location) {

        StringBuffer str = new StringBuffer("Exception closing down ");

        str.append(message);
        str.append(" at ");
        str.append(location);
        str.append(" Press any key to exit");

        return str.toString();
    }

    private static String StringBuilderMethod(String message, String location) {

        StringBuilder str = new StringBuilder("Exception closing down ");

        str.append(message);
        str.append(" at ");
        str.append(location);
        str.append(" Press any key to exit");

        return str.toString();
    }

}

На моєму Intel i5 я отримав:
Using Strings took 73912nS
Using StringBuffer took 26563nS
Using StringBuilder took 10394nS


Продуктивність String vs StringBuilder вражаюча 700% на користь StringBuilder. Отже дуже раджу не лінитисьі використовувати StringBuilder!

Стосовно StringBuilder vs StringBuffer, то на перший погляд тут також просто - StringBuffer Thread safe. StringBuffer обов'язково потрібно використовувати, коли ви маєте багатопотокову систему.

Але от коли у вас не багатопотокова система, то тут не все так однозначно. В Java є така магічна річ як JIT, яка може видалити сихронізацію потоків і вирівняти продуктивнсть. Тож не потрібно обов'язково заміняти в легасі коді StringBuilder на StringBuilde, можливо, синхронізація і так видаляється. 

Магія String Utils.

Клас String  має достатньо багато інструментів, які нам допомагають зробити дуже багато речей найоптимальнішим шляхом, також Java має цілий набір класів які допомагають в маніпулюванні стрінгами. Але я б радив вам звернути увагу на сет спеціалізованих бібліотек, які ще більше полегшать життя кожному:
-Apache Commons - тут можна знайти цілу купу надзвичайно корисних дрібничок
-Google Guava - просто фантастична кількість утилітних класів
-Spring Utils - ще один додаток, який робить світ Spring самодостаттнім.

ПС: Як написано нижче - ми намагаємось освіжити JUG і зробити його актуальнішим, але без ваших відгукув - це неможливо!!! Чекаємо на ваші думки, побажання, пропозиції ось тут: http://jug-lviv.blogspot.com/2012/10/jug-reset.html




9 коментарів:

  1. взагалі то перший приклад демонструє факт копіювання по значенню (проти референсу), а зовсім не іммутабельність стрінга

    ВідповістиВидалити
  2. Нажаль Костянтин мушу з тобою не погодитись.
    Це достатньо складна тема і я не знайшов ні одного посилання, де б прямо говорилось, що стрінг передається за значенням.
    Ось приклад статті: http://www.coderanch.com/t/392784/java/java/Passing-String-reference

    Як я розумію, то в методі створюється копія посилання (4 байти), які вказують на об"єкт, коли ми робимо val ="not object"; в змінна переписується нова адреса на новий об"єкт.

    Якщо матимеш посилання на це - радо почитаю і зміню свою думку.

    ВідповістиВидалити
    Відповіді
    1. >>> в змінна переписується нова адреса на новий об"єкт

      саме це мав на увазі Костянтин, а отже жодного натяку на імутабельність.

      хорошим прикладом імутабельності, натомість, могли б бути BigDecimal або якийсь із класів часу або дати у joda-time. Особливо беручи до уваги їхні методи додавання, віднімання і т.д.

      Видалити
  3. Перш за все кульно - хтось читає моє писалово:).

    Стосовно Констянтина, то питання було в тому як передається значення в метод.
    А стосовно імутабле, то тут погоджуюсь не зовсі зрозуміло висловився - перепишу.

    ПС. Може хтось матиме бажання ще щось написати ? :)

    ВідповістиВидалити
    Відповіді
    1. When the method or constructor is invoked (§15.12), the values of the actual argument expressions initialize newly created parameter variables, each of the declared type, before execution of the body of the method or constructor.
      Java Language Specification http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.1

      Видалити
    2. Автор видалив цей коментар.

      Видалити
    3. як такого - питання не було. я лише зауважив, що перший приклад не ілюструє імутабільність стрінгів, а є чудовим прикладом pass-by-value

      Видалити
  4. Дякую за коменти. Просто вреженний - це блог хтось читає :).

    Як я казав виправлю :)

    ВідповістиВидалити
    Відповіді
    1. читають :)
      тре періодично щось суперечливе постати, щоб активізувати блог ;)

      Видалити