简体   繁体   English

字符串和长字符串列表

[英]List of String and long String

Suppose I have a list of Book where the number of books can be quite large.假设我有一个 Book 列表,其中书籍的数量可能非常大。 I'm logging the isbn of those books.我正在记录那些书的 isbn。 I've come up with two approaches, would there be any performance difference / which approach is considered as better?我想出了两种方法,会有任何性能差异/哪种方法被认为更好?

My concern with 2) will be whether the length of String is too long to become an issue.我对 2) 的担忧是 String 的长度是否太长而不会成为问题。 Refer to How many characters can a Java String have?请参阅Java 字符串可以有多少个字符? , it's not likely it will hit the max number of characters, but I'm not sure on the point about "Half your maximum heap size", and whether it's actually a good practice to construct a long String. ,它不太可能达到最大字符数,但我不确定“一半的最大堆大小”这一点,以及构造一个长字符串是否真的是一个好习惯。

  1. Convert to list of String转换为字符串列表
List<Book> books = new ArrayList<>();
books.add(new Book().name("book1").isbn("001"));
books.add(new Book().name("book2").isbn("002"));

if (books != null && books.size() > 0) {
  List<String> isbns = books.stream()
                            .map(Book:getIsbn)
                            .collect(Collectors.toList());
  logger.info("List of isbn = {}", isbns);
} else {
  logger.info("Empty list of isbn");
}
  1. Using StringBuilder and concatenate as one long String使用 StringBuilder 并连接为一个长字符串
List<Book> books = new ArrayList<>();
books.add(new Book().name("book1").isbn("001"));
books.add(new Book().name("book2").isbn("002"));

if (books != null && books.size() > 0) {
  StringBuilder strB = new StringBuilder();
  strB.append("List of isbn: ");
  books.stream()
       .forEach(book -> {
         strB.append(book.getIsbn());
         strB.append("; ");
       });
  logger.info("List of isbn = {}", strB.toString());
} else {
  logger.info("Empty list of isbn");
}

... but I'm not sure on the point about "Half your maximum heap size" ...但我不确定“一半你的最大堆大小”

The JVM heap has a maximum size set by command line options, or by defaults. JVM 堆的最大大小由命令行选项或默认设置。 If you fill the heap, your JVM will throw and OutOfMemoryError (OOME) and that will typically cause your application to terminate (or worse.).如果您填满了堆,您的 JVM 将抛出OutOfMemoryError (OOME),这通常会导致您的应用程序终止(或更糟)。

When you construct a string using a StringBuilder the builder uses a roughly exponential resizing strategy.当您使用StringBuilder构造字符串时,构建器使用大致指数调整大小的策略。 When you fill the builder's buffer, it allocates a new one with double the size.当您填充构建器的缓冲区时,它会分配一个大小为两倍的新缓冲区。 But the old and new buffers need to exist at the same time.但是新旧缓冲区需要同时存在。 So when the buffer is between 1/2 and 2/3rds of the size of the entire heap, and the buffer fills up, the StringBuilder will attempt allocate a new buffer that is larger than the remaining available space and an OOME will ensue.因此,当缓冲区在整个堆大小的 1/2 到 2/3 之间,并且缓冲区已填满时, StringBuilder将尝试分配一个大于剩余可用空间的新缓冲区,并且会发生 OOME。


Having said that, assembling a single string containing a huge amount of data is going to be bad for performance even if you don't trigger an OOME.话虽如此,即使您不触发 OOME,组装包含大量数据的单个字符串也会对性能不利。 A better idea is to write the data via a buffers OutputStream or Writer .更好的想法是通过缓冲区OutputStreamWriter写入数据。

This may be problematic if you are outputting the data via a Logger .如果您通过Logger输出数据,这可能会出现问题。 But I wouldn't try to use a Logger for that.但我不会尝试为此使用Logger And I certainly wouldn't try to do it using a single Logger.info(...) call.我当然不会尝试使用单个Logger.info(...)调用来做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM