Создать переменную Java (String) определенного размера (МБ) - PullRequest
13 голосов
/ 19 марта 2010

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

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

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();
  }

Ответы [ 4 ]

35 голосов
/ 19 марта 2010

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

char[] data = new char[1000000];

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

String str = new String(data);

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

23 голосов
/ 19 марта 2010

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

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

String str = new String(chars);

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

20 голосов
/ 19 марта 2010

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

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

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

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

фактически означает:

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

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

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

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

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

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

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

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

sb.append('a');

вместо:

sb.append("a");

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

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

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

0 голосов
/ 19 марта 2010

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

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...