System.out.println("Input String length : " + str.length());
System.out.println("SWB==="+sw.getTime());
byte[] bytes = Base64.decodeBase64(str);
System.out.println("SWB==="+sw.getTime());
GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes));
BufferedReader bf = new BufferedReader(new InputStreamReader(gis));
String outStr = "";
String line;
while ((line=bf.readLine())!=null) {
outStr += line;
}
System.out.println("SWB==="+sw.getTime());
System.out.println("Output String lenght : " + outStr.length());
Вышеприведенный код печатает
SWB===1
SWB===4
SWB===27052
Output String lenght : 1750825
Но сжатие одной и той же строки занимает довольно короткое время (менее 100 мс). Что я здесь делаю неправильно? (кроме моего плохого способа отладки комментариев)
Проблема заключается в следующем:
String line;
while ((line=bf.readLine())!=null) {
outStr += line;
}
Каждая String
конкатенация будет неявно создать StringBuilder
, добавляемых в 2 строки, а затем вызвать toString()
метод на нем.
Используйте один StringBuilder
чтобы резко ускорить это:
StringBuilder sb = new StringBuilder(65536); // Consider a large initial size
String line
while ((line=bf.readLine())!=null) {
sb.append(line);
}
// OutString is in the sb StringBuilder
String outStr = sb.toString();
Также рассмотрите большой начальный размер StringBuilder
чтобы минимизировать внутренние перераспределения. В примере я использовал 64 КБ, но если вы знаете свой результат, String
будет намного больше, вы можете даже безопасно использовать несколько MB.
Также подумайте о том, чтобы не вызвать toString()
для результата, если он вам не нужен. StringBuilder
реализует CharSequence
и многие методы принимают CharSequence
, а также String
s.
StringBuilder
вместоoutStr += line
.