1 Востаннє редагувалося Kane (11.02.2015 18:01:38)

Тема: StringBuilder в якості аргумента методу, або..?

Всім привіт.

import java.util.Scanner;

public class FirstClass {
    public static String IntToBin(StringBuilder b, int val) {
        int mask = 0x80000000;

        while(mask != 0) {
            b.append((val & mask) != 0 ? '1' : '0');
            mask >>>= 1;

            if(mask == 0x800000 || mask == 0x8000 || mask == 0x80)
                b.append('-');
        }

        return b.toString();
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        StringBuilder b = new StringBuilder();
        int i;

        while(true) {
            System.out.print("Введіть число або '0' для виходу: "); 
            i = in.nextInt();

            if (i != 0) {
                System.out.println(IntToBin(b, i));
                b.delete(0, b.length());
            }
            else break;
        }

        System.out.print("exit!");
    }
}

Як воно зі сторони "оптимізації" краще буде: StringBuilder передавати в якості аргумента та при кожній ітерації його очищати, чи зашити його в метод та покластись на gc?

2 Востаннє редагувалося quez (11.02.2015 18:35:39)

Re: StringBuilder в якості аргумента методу, або..?

Це ж не C, тут delete не завжди значить delete :)

  public AbstractStringBuilder  delete(int start, int end) {
         if (start < 0)
             throw new StringIndexOutOfBoundsException(start);
         if (end > count)
             end = count;
         if (start > end)
             throw new StringIndexOutOfBoundsException();
         int len = end - start;
         if (len > 0) {

             System.arraycopy(value, start+len, value, start, count-end);
             count -= len;
         }
         return this;
     }

Метод delete просто копіює все те, що знаходиться після символів, які підлягають видаленню, на місце символів, які потрібно видалити. Фізично пам'ять не очищується, масив залишається такої ж довжини. Робіть висновки.

Подякували: Kane1

3

Re: StringBuilder в якості аргумента методу, або..?

Передавати як аргумент допоміжну змінну, яка на місці виклику не використовується — не дуже гарний стиль. Краще оголосити static StringBuilder b=new StringBuilder(); у тілі класу, а аргумент b викинути. Очищення можна робити на початку IntToBin().

Подякували: Kane1

4

Re: StringBuilder в якості аргумента методу, або..?

Метод delete просто копіює все те, що знаходиться після символів, які підлягають видаленню, на місце символів, які потрібно видалити. Фізично пам'ять не очищується, масив залишається такої ж довжини. Робіть висновки.

Якщо видаляємо все від першого символа до останнього, то, з точки зору продуктивності, так навіть краще: пам'ять лишається виділеною до наступного разу, а не виділяється/знищується кожен раз (що може давати сповільнення, навантажувати сміттєзбирача і т.д.).

5

Re: StringBuilder в якості аргумента методу, або..?

P.Y. написав:

Метод delete просто копіює все те, що знаходиться після символів, які підлягають видаленню, на місце символів, які потрібно видалити. Фізично пам'ять не очищується, масив залишається такої ж довжини. Робіть висновки.

Якщо видаляємо все від першого символа до останнього, то, з точки зору продуктивності, так навіть краще: пам'ять лишається виділеною до наступного разу, а не виділяється/знищується кожен раз (що може давати сповільнення, навантажувати сміттєзбирача і т.д.).

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

Тому спочатку варто було б згідно з правилами хорошого стилю оголосити StringBuilder всередині методу (якщо сходу не буде зрозуміло, що саме він буде горлом пляшки), а потім при потребі змінити.

6

Re: StringBuilder в якості аргумента методу, або..?

Не думаю, що в часи кількагігабайтних оперативок виділений хай навіть кілобайтний блок пам'яті буде створювати незручності. А от якщо цих блоків, великих і маленьких, висітиме вже ціла черга, доки до них не добереться сміттєзбирач, це вже може створити певні незручності. Питання стосувалось продуктивності. Якщо функція часто й багато викликається, особливо в циклі, то для оптимізації стрингбілдер можна зробити статичним. Якщо цієї проблеми нема, то правильним стилем буде розмістити стрингбілдер у функції локально.

Ще одне. Якщо ця функція викликатиметься в паралельних потоках, варіант із статичним полем не годиться — можливий ризик, коли два потоки почнуть одночасно кидати в буфер дані.