如何在 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);
}

如果允许单个语句与 ifwhile 语句在同一行,它会更加简洁。

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