如何在 java 或 Kotlin 中拆分数组?
How to split an array in java or Kotlin?
我们如何拆分对象数组?例如,我有多种这样的字符:
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
我想用位置 6 的空格拆分数组。拆分后,集合将如下所示:
Array1 = ['H', 'e', 'l', 'l', 'o']
Array2 = ['W', 'o', 'r', 'l', 'd']
我确实在 here 上找到了 post 类似的东西,但 java 或 Kotlin 中没有。
我知道我可以这样做:
String str = TextUtils.join(",", arr);
String[] splittedString = str.split(" ");
但是,如果可能的话,我想要另一种方式。使用这种.split
方法会占用大量内存,在大型数组上大约需要 30-40 毫秒。
如何使用 java 或 Kotlin 执行此操作?
一个简单的解决方案是将原始数组连接成一个字符串,按 space 拆分,然后再次拆分为字符(在 kotlin 中):
arr.joinToString().split(" ").map{ it.split() }
这没有优化,但仍处于 O(n)
(线性复杂度)。它受益于可读性,这通常应该是首选,而如果这对您手头的任务至关重要,则应该解决性能问题。
将数组转换为字符串并将其拆分为 Java:
final String[] array = { "H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d" };
final String[] arr = String.join("", array).split(" ");
final String[] subArray1 = arr[0].split("");
final String[] subArray2 = arr[1].split("");
在 Java 中这样做是为了好玩。虽然不是很简洁。我似乎无法正确使用 Streams 来做到这一点。
public static void main(String[] args) {
char[] chars = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
char[][] char2d;
String[] tokens = String.valueOf(chars).split(" ");
char2d = new char[tokens.length][];
for (int i=0; i< tokens.length; i++) {
char2d[i] = tokens[i].toCharArray();
}
for (int i=0; i< char2d.length; i++){
System.out.println(Arrays.toString(char2d[i]));
}
}
输出:
[H, e, l, l, o]
[W, o, r, l, d]
设法用流复制它,如下所示:
char[][] char2d2 = Arrays.stream(tokens).map(String::toCharArray).toArray(char[][]::new);
for (int i=0; i< char2d2.length; i++){
System.out.println(Arrays.toString(char2d2[i]));
}
给出与上面相同的输出。
我假设一个通用数组的元素确实具有 Object::equals
的正确实现;对于单纯的数组char
,建议的基于String操作的解决方案是最有效的实现。
试试这个:
final Element [] input = …
final Element split = …
final List<Element[]> output = new ArrayList<>();
var start = 0;
var end = 0;
while( end < input.length )
{
if( input [end].equals( split ) )
{
output.add( Arrays.copyOfRange( input( start, end ) ) );
start = end + 1;
}
++end;
}
if( start < end ) output.add( Arrays.copyOfRange( input( start, end ) ) );
这是一种只使用额外的 ArrayList 和 StringBuilder 的方法,无需将整个输入转换为字符串。
String[] splitOnSpaces(char[] chars) {
List<String> strings = new ArrayList<>();
StringBuilder word = new StringBuilder();
for (int i = 0; i < chars.length; ) {
while (i < chars.length && chars[i] == ' ') {
++i;
}
while (i < chars.length && chars[i] != ' ') {
word.append(chars[i++]);
}
if (word.length() > 0) {
strings.add(word.toString());
word.setLength(0);
}
}
return strings.toArray(String[]::new);
}
如果允许单个语句与 if
或 while
语句在同一行,它会更加简洁。
String[] splitOnSpaces(char[] chars) {
List<String> strings = new ArrayList<>();
StringBuilder word = new StringBuilder();
for (int i = 0; i < chars.length; ) {
while (i < chars.length && chars[i] == ' ') ++i;
while (i < chars.length && chars[i] != ' ') word.append(chars[i++]);
if (word.length() > 0) strings.add(word.toString());
word.setLength(0);
}
return strings.toArray(String[]::new);
}
我们如何拆分对象数组?例如,我有多种这样的字符:
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
我想用位置 6 的空格拆分数组。拆分后,集合将如下所示:
Array1 = ['H', 'e', 'l', 'l', 'o']
Array2 = ['W', 'o', 'r', 'l', 'd']
我确实在 here 上找到了 post 类似的东西,但 java 或 Kotlin 中没有。
我知道我可以这样做:
String str = TextUtils.join(",", arr);
String[] splittedString = str.split(" ");
但是,如果可能的话,我想要另一种方式。使用这种.split
方法会占用大量内存,在大型数组上大约需要 30-40 毫秒。
如何使用 java 或 Kotlin 执行此操作?
一个简单的解决方案是将原始数组连接成一个字符串,按 space 拆分,然后再次拆分为字符(在 kotlin 中):
arr.joinToString().split(" ").map{ it.split() }
这没有优化,但仍处于 O(n)
(线性复杂度)。它受益于可读性,这通常应该是首选,而如果这对您手头的任务至关重要,则应该解决性能问题。
将数组转换为字符串并将其拆分为 Java:
final String[] array = { "H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d" };
final String[] arr = String.join("", array).split(" ");
final String[] subArray1 = arr[0].split("");
final String[] subArray2 = arr[1].split("");
在 Java 中这样做是为了好玩。虽然不是很简洁。我似乎无法正确使用 Streams 来做到这一点。
public static void main(String[] args) {
char[] chars = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
char[][] char2d;
String[] tokens = String.valueOf(chars).split(" ");
char2d = new char[tokens.length][];
for (int i=0; i< tokens.length; i++) {
char2d[i] = tokens[i].toCharArray();
}
for (int i=0; i< char2d.length; i++){
System.out.println(Arrays.toString(char2d[i]));
}
}
输出:
[H, e, l, l, o]
[W, o, r, l, d]
设法用流复制它,如下所示:
char[][] char2d2 = Arrays.stream(tokens).map(String::toCharArray).toArray(char[][]::new);
for (int i=0; i< char2d2.length; i++){
System.out.println(Arrays.toString(char2d2[i]));
}
给出与上面相同的输出。
我假设一个通用数组的元素确实具有 Object::equals
的正确实现;对于单纯的数组char
,建议的基于String操作的解决方案是最有效的实现。
试试这个:
final Element [] input = …
final Element split = …
final List<Element[]> output = new ArrayList<>();
var start = 0;
var end = 0;
while( end < input.length )
{
if( input [end].equals( split ) )
{
output.add( Arrays.copyOfRange( input( start, end ) ) );
start = end + 1;
}
++end;
}
if( start < end ) output.add( Arrays.copyOfRange( input( start, end ) ) );
这是一种只使用额外的 ArrayList 和 StringBuilder 的方法,无需将整个输入转换为字符串。
String[] splitOnSpaces(char[] chars) {
List<String> strings = new ArrayList<>();
StringBuilder word = new StringBuilder();
for (int i = 0; i < chars.length; ) {
while (i < chars.length && chars[i] == ' ') {
++i;
}
while (i < chars.length && chars[i] != ' ') {
word.append(chars[i++]);
}
if (word.length() > 0) {
strings.add(word.toString());
word.setLength(0);
}
}
return strings.toArray(String[]::new);
}
如果允许单个语句与 if
或 while
语句在同一行,它会更加简洁。
String[] splitOnSpaces(char[] chars) {
List<String> strings = new ArrayList<>();
StringBuilder word = new StringBuilder();
for (int i = 0; i < chars.length; ) {
while (i < chars.length && chars[i] == ' ') ++i;
while (i < chars.length && chars[i] != ' ') word.append(chars[i++]);
if (word.length() > 0) strings.add(word.toString());
word.setLength(0);
}
return strings.toArray(String[]::new);
}