用Java将List<char[]>
转换/扁平化为char[]
的简单方法是什么?
我知道我可以通过迭代List
和使用System.arraycopy
来完成这个任务,但是我想知道是否有更简单的方法可以使用Java8Streams来完成它呢?
可能是这样的,但不必将原语char
设置为Character
List<char[]> listOfCharArrays = ...
Character[] charArray =
Stream.of(listOfCharArrays )
.flatMap(List::stream)
.toArray(Character[]::new);
发布于 2022-06-20 02:06:39
我只能想到一件事,那就是使用CharBuffer
。出于效率原因,我总是先计算出正确的大小,然后执行副本。任何执行多个副本和/或执行字符串处理的解决方案都将效率低下。
这是密码。第一行计算所需数组的总大小,然后为其分配足够的内存。第二行使用前面提到的put
方法执行复制。最后一行返回支持CharBuffer
的CharBuffer
。
CharBuffer fullBuffer = CharBuffer.allocate(
listOfCharArrays.stream().mapToInt(array -> array.length).sum());
listOfCharArrays.forEach(fullBuffer::put);
char[] asCharArray = fullBuffer.array();
当然,我不能保证它不会在System.arrayCopy
方法的某个地方使用CharBuffer#put
。我强烈期望它在内部使用System.arrayCopy
或类似的代码。不过,这可能适用于这里提供的大多数解决方案。
如果可以估计最大大小,则可以通过使用足够大的缓冲区来避免第一次大小计算,但它将需要缓冲区中数据的额外副本;CharBuffer#array
只返回大小正确的支持数组,这意味着数据只复制一次。
如果您想使用面向对象的代码,也可以直接使用CharBuffer
。但是,请注意,您需要确保在写入flip
之后,CharBuffer
是可变的(您可以使用duplicate
或asReadOnly
方法传递副本--返回的实例引用相同的缓冲区,但具有独立的、可变的“位置”和“限制”字段)。
Buffer
和Java类有点难理解,但是一旦理解了,您就可以从它们中获得很大的好处,例如在CharEncoder
或内存映射文件中使用它们时。
发布于 2022-06-20 01:55:04
这是我能想到的最可读的版本。您可以通过StringBuilder将所有char数组附加到字符串中,然后将其转换为char[]
。
char[] chars = listOfCharArrays.stream()
.collect(Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString))
.toCharArray();
可能比迭代版本慢得多,因为arrayCopy
可以复制内存块。
您可以考虑预先计算字符的总数,以避免重新分配StringBuilder数组,但是这种优化和任何其他优化都会占用您从使用流中获得的可读性增益。
int totalSize = listOfCharArrays.stream().mapToInt(arr -> arr.length).sum();
char[] chars = listOfCharArrays.stream()
.collect(Collector.of(() -> new StringBuilder(totalSize), //... the same
有两个不必要的副本(StringBuilder
-> String
,String
-> char[]
),它们实际上是这些类不完全适合此任务的结果。CharBuffer
更适合;参见Maarten's answer。
发布于 2022-06-20 02:05:51
它可以通过字符串,或者更确切地说是一个CharBuffer来完成,就像Holger评论的那样。
char[] flatten(List<char[]> list) {
return list.stream()
.map(CharBuffer::wrap) // Better than String::new
.collect(Collectors.joining())
.toCharArray();
}
这需要“完成”数组,而在开始或结束时没有任何不完整的代理对字符。
因此,将其与以下内容进行比较:
char[] flatten(List<char[]> list) {
int totalLength = list.stream().mapToInt(a -> a.length).sum();
char[] totalArray = new char[totalLength];
int i = 0;
for (char[] array : list) {
System.arraycopy(array, 0, totalArray, i, array.length);
i += array.length;
}
return totalArray;
}
没那么大的差别,更可靠的代码。
或者将整个软件放在不可变的String
上而不是char[]
上。
https://stackoverflow.com/questions/72684930
复制相似问题