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

Создайте переменную Java (String) определенного размера (МБ)

Я пытаюсь сравнить некоторый код. Я отправляю String msg через сокеты. Я хочу отправить переменные String 100KB, 2MB и 10MB. Есть ли простой способ создать переменную этих размеров?

В настоящее время я делаю это.

private static String createDataSize(int msgSize) {
    String data = "a";
    while(data.length() < (msgSize*1024)-6) {
        data += "a";
    }
    return data;
}

Но это занимает очень много времени. Есть ли лучший способ?

UPDATE: Спасибо, я делаю это сейчас.

/**
 * Creates a message of size @msgSize in KB.
 */
private static String createDataSize(int msgSize) {
    // Java chars are 2 bytes
    msgSize = msgSize/2;
    msgSize = msgSize * 1024;
    StringBuilder sb = new StringBuilder(msgSize);
    for (int i=0; i<msgSize; i++) {
        sb.append('a');
    }
    return sb.toString();
  }
4b9b3361

Ответ 1

Java char имеет размер 2 байта (16 бит без знака). Поэтому, если вы хотите 2 МБ, вам нужно миллион символов. В коде есть две очевидные проблемы:

  • Повторное вызов length() не требуется. Добавьте любого символа в Java String, и длина его увеличивается на 1, независимо от того, какой символ. Возможно, вы путаете это с размером в байтах. Это не значит, что; и
  • У вас есть огромные проблемы с фрагментацией памяти с этим кодом.

Чтобы пояснить (2), оператор конкатенации строк (+) в Java вызывает создание нового String, потому что Java String неизменяемы. Итак:

String a = "a";
a += "b";

на самом деле означает:

String a = "a";
String a = a + "b";

Это иногда путает бывших программистов на С++, поскольку строки работают по-другому в С++.

Таким образом, ваш код фактически выделяет миллион строк для размера сообщения в миллион. Остается только последний. Другие - мусор, который будет очищен, но в этом нет необходимости.

Лучшая версия:

private static String createDataSize(int msgSize) {
  StringBuilder sb = new StringBuilder(msgSize);
  for (int i=0; i<msgSize; i++) {
    sb.append('a');
  }
  return sb.toString();
}

Ключевым отличием является то, что:

  • A StringBuilder является изменяемым, поэтому его не нужно перераспределять с каждым изменением; и
  • В этом примере кода StringBuilder предварительно распределяется до нужного размера.

Примечание: проницательный, возможно, заметил, что я сделал:

sb.append('a');

а не:

sb.append("a");

'a', конечно, является одним символом, "a" является String. Вы можете использовать либо в этом случае.

Однако это не так просто, потому что это зависит от того, как кодируются байты. Обычно, если вы не укажете его иначе, он будет использовать UTF8, который является символами переменной ширины. Таким образом, миллион символов может быть где угодно от 1 МБ до 4 МБ в зависимости от того, в конечном итоге вы его кодируете, и ваш вопрос не содержит подробностей.

Если вам нужны данные определенного размера, и эти данные не имеют значения, моим советом было бы просто использовать массив byte нужного размера.

Ответ 2

Вы можете просто создать большой массив символов.

char[] data = new char[1000000];

Если вам нужно создать реальный объект String, вы можете:

String str = new String(data);

Не используйте += для создания строк в цикле. Это имеет память O (n²) и время использования, поскольку объекты String неизменяемы (так что каждый раз, когда вы вызываете +=), должен быть создан новый объект String, копируя все содержимое старой строки в процесс).

Ответ 3

Используйте char [] либо напрямую, либо для создания строки.

char[] chars = new char[size];
Arrays.fill(chars, 'a');

String str = new String(chars);

Также обратите внимание, что один char использует два байта внутри. Как долго String будет по проводам, зависит от кодировки (буква a должна быть только одним байтом).

Ответ 4

да, есть.. с использованием буферизованного строкового объекта:

StringBuilder stringB = new StringBuilder(2000000); //for the 2mb one
String paddingString = "abcdefghijklmnopqrs";

while (stringB.length() + paddingString.length() < 2000000)
 stringB.append(paddingString);

//use it
stringB.toString()