在Java中,将字符串分割为相等长度的子字符串

时间:2022-12-27 21:41:48

How to split the string "Thequickbrownfoxjumps" to substrings of equal size in Java. Eg. "Thequickbrownfoxjumps" of 4 equal size should give the output.

如何分割字符串“thequickbrownfoxjump”到Java中大小相同的子字符串。如。4个大小相同的“快速的棕色狐狸跳跃”应该给出输出。

["Theq","uick","brow","nfox","jump","s"]

Similar Question:

类似的问题:

Split string into equal-length substrings in Scala

在Scala中将字符串分割成等长子字符串

14 个解决方案

#1


178  

Here's the regex one-liner version:

以下是regex单行版本:

System.out.println(Arrays.toString(
    "Thequickbrownfoxjumps".split("(?<=\\G.{4})")
));

\G is a zero-width assertion that matches the position where the previous match ended. If there was no previous match, it matches the beginning of the input, the same as \A. The enclosing lookbehind matches the position that's four characters along from the end of the last match.

\G是一个零宽度断言,它匹配上一场比赛结束的位置。如果没有以前的匹配,它匹配输入的开始,和\A一样。包含的lookbehind与最后一场比赛结束时的四个字符的位置匹配。

Both lookbehind and \G are advanced regex features, not supported by all flavors. Furthermore, \G is not implemented consistently across the flavors that do support it. This trick will work (for example) in Java, Perl, .NET and JGSoft, but not in PHP (PCRE), Ruby 1.9+ or TextMate (both Oniguruma). JavaScript's /y (sticky flag) isn't as flexible as \G, and couldn't be used this way even if JS did support lookbehind.

lookbehind和\G都是高级regex功能,并不是所有口味都支持。而且,\G并没有在支持它的口味上一致地实现。这个技巧可以在Java、Perl、. net和JGSoft中使用(例如),但不能在PHP (PCRE)、Ruby 1.9+或TextMate(两者都是Oniguruma)中使用。JavaScript /y(粘贴标记)没有\G那么灵活,即使JS支持lookbehind,也不能用这种方式。

I should mention that I don't necessarily recommend this solution if you have other options. The non-regex solutions in the other answers may be longer, but they're also self-documenting; this one's just about the opposite of that. ;)

我应该指出,如果您有其他的选择,我并不一定推荐这种解决方案。其他答案中的非regex解决方案可能更长,但它们也是自文档化的;这个和那个刚好相反。,)

Also, this doesn't work in Android, which doesn't support the use of \G in lookbehinds.

此外,这在Android中也不适用,Android不支持在后视镜中使用\G。

#2


107  

Well, it's fairly easy to do this by brute force:

这很容易用蛮力来做:

public static List<String> splitEqually(String text, int size) {
    // Give the list the right capacity to start with. You could use an array
    // instead if you wanted.
    List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);

    for (int start = 0; start < text.length(); start += size) {
        ret.add(text.substring(start, Math.min(text.length(), start + size)));
    }
    return ret;
}

I don't think it's really worth using a regex for this.

我不认为它真的值得使用regex。

EDIT: My reasoning for not using a regex:

编辑:我不使用regex的理由:

  • This doesn't use any of the real pattern matching of regexes. It's just counting.
  • 这并不使用regex的任何实际模式匹配。它只是计数。
  • I suspect the above will be more efficient, although in most cases it won't matter
  • 我怀疑上面的方法会更有效,尽管在大多数情况下这并不重要
  • If you need to use variable sizes in different places, you've either got repetition or a helper function to build the regex itself based on a parameter - ick.
  • 如果您需要在不同的地方使用可变大小,那么您要么得到了重复,要么得到了一个辅助函数,以基于参数- ick来构建regex本身。
  • The regex provided in another answer firstly didn't compile (invalid escaping), and then didn't work. My code worked first time. That's more a testament to the usability of regexes vs plain code, IMO.
  • 另一个答案中提供的regex首先没有编译(无效转义),然后没有工作。我的代码第一次运行。在我看来,这更证明了regexes和普通代码的可用性。

#3


60  

This is very easy with Google Guava:

用谷歌番石榴很容易:

for(final String token :
    Splitter
        .fixedLength(4)
        .split("Thequickbrownfoxjumps")){
    System.out.println(token);
}

Output:

输出:

Theq
uick
brow
nfox
jump
s

Or if you need the result as an array, you can use this code:

或者,如果您需要结果作为数组,您可以使用以下代码:

String[] tokens =
    Iterables.toArray(
        Splitter
            .fixedLength(4)
            .split("Thequickbrownfoxjumps"),
        String.class
    );

Reference:

参考:

Note: Splitter construction is shown inline above, but since Splitters are immutable and reusable, it's a good practice to store them in constants:

注意:Splitter结构在上面的内联显示,但是由于Splitters是不可变的和可重用的,所以最好将它们存储在常量中:

private static final Splitter FOUR_LETTERS = Splitter.fixedLength(4);

// more code

for(final String token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){
    System.out.println(token);
}

#4


11  

If you're using Google's guava general-purpose libraries (and quite honestly, any new Java project probably should be), this is insanely trivial with the Splitter class:

如果您正在使用谷歌的guava通用库(老实说,任何新的Java项目都应该是这样),那么对于Splitter类来说,这简直是小菜一碟:

for (String substring : Splitter.fixedLength(4).split(inputString)) {
    doSomethingWith(substring);
}

and that's it. Easy as!

就是这样。简单!

#5


6  

public static String[] split(String src, int len) {
    String[] result = new String[(int)Math.ceil((double)src.length()/(double)len)];
    for (int i=0; i<result.length; i++)
        result[i] = src.substring(i*len, Math.min(src.length(), (i+1)*len));
    return result;
}

#6


4  

public String[] splitInParts(String s, int partLength)
{
    int len = s.length();

    // Number of parts
    int nparts = (len + partLength - 1) / partLength;
    String parts[] = new String[nparts];

    // Break into parts
    int offset= 0;
    int i = 0;
    while (i < nparts)
    {
        parts[i] = s.substring(offset, Math.min(offset + partLength, len));
        offset += partLength;
        i++;
    }

    return parts;
}

#7


3  

You can use substring from String.class (handling exceptions) or from Apache lang commons (it handles exceptions for you)

可以使用字符串中的子字符串。类(处理异常)或Apache lang commons(它为您处理异常)

static String   substring(String str, int start, int end) 

Put it inside a loop and you are good to go.

把它放入一个循环中,你就可以开始了。

#8


2  

I'd rather this simple solution:

我宁愿要一个简单的解决办法:

String content = "Thequickbrownfoxjumps";
while(content.length() > 4) {
    System.out.println(content.substring(0, 4));
    content = content.substring(4);
}
System.out.println(content);

#9


1  

In case you want to split the string equally backwards, i.e. from right to left, for example, to split 1010001111 to [10, 1000, 1111], here's the code:

如果您想要将字符串平均向后拆分,例如,从右到左,将1010001111拆分为[10,1000,1111],下面是代码:

/**
 * @param s         the string to be split
 * @param subLen    length of the equal-length substrings.
 * @param backwards true if the splitting is from right to left, false otherwise
 * @return an array of equal-length substrings
 * @throws ArithmeticException: / by zero when subLen == 0
 */
public static String[] split(String s, int subLen, boolean backwards) {
    assert s != null;
    int groups = s.length() % subLen == 0 ? s.length() / subLen : s.length() / subLen + 1;
    String[] strs = new String[groups];
    if (backwards) {
        for (int i = 0; i < groups; i++) {
            int beginIndex = s.length() - subLen * (i + 1);
            int endIndex = beginIndex + subLen;
            if (beginIndex < 0)
                beginIndex = 0;
            strs[groups - i - 1] = s.substring(beginIndex, endIndex);
        }
    } else {
        for (int i = 0; i < groups; i++) {
            int beginIndex = subLen * i;
            int endIndex = beginIndex + subLen;
            if (endIndex > s.length())
                endIndex = s.length();
            strs[i] = s.substring(beginIndex, endIndex);
        }
    }
    return strs;
}

#10


0  

I asked @Alan Moore in a comment to the accepted solution how strings with newlines could be handled. He suggested using DOTALL.

我在接受的解决方案中询问@Alan Moore如何处理带有换行的字符串。他建议使用DOTALL。

Using his suggestion I created a small sample of how that works:

利用他的建议,我创建了一个小样本,它是如何工作的:

public void regexDotAllExample() throws UnsupportedEncodingException {
    final String input = "The\nquick\nbrown\r\nfox\rjumps";
    final String regex = "(?<=\\G.{4})";

    Pattern splitByLengthPattern;
    String[] split;

    splitByLengthPattern = Pattern.compile(regex);
    split = splitByLengthPattern.split(input);
    System.out.println("---- Without DOTALL ----");
    for (int i = 0; i < split.length; i++) {
        byte[] s = split[i].getBytes("utf-8");
        System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
    }
    /* Output is a single entry longer than the desired split size:
    ---- Without DOTALL ----
    [Idx: 0, length: 26] - [B@17cdc4a5
     */


    //DOTALL suggested in Alan Moores comment on SO: https://*.com/a/3761521/1237974
    splitByLengthPattern = Pattern.compile(regex, Pattern.DOTALL);
    split = splitByLengthPattern.split(input);
    System.out.println("---- With DOTALL ----");
    for (int i = 0; i < split.length; i++) {
        byte[] s = split[i].getBytes("utf-8");
        System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
    }
    /* Output is as desired 7 entries with each entry having a max length of 4:
    ---- With DOTALL ----
    [Idx: 0, length: 4] - [B@77b22abc
    [Idx: 1, length: 4] - [B@5213da08
    [Idx: 2, length: 4] - [B@154f6d51
    [Idx: 3, length: 4] - [B@1191ebc5
    [Idx: 4, length: 4] - [B@30ddb86
    [Idx: 5, length: 4] - [B@2c73bfb
    [Idx: 6, length: 2] - [B@6632dd29
     */

}

But I like @Jon Skeets solution in https://*.com/a/3760193/1237974 also. For maintainability in larger projects where not everyone are equally experienced in Regular expressions I would probably use Jons solution.

但是我也喜欢https://*.com/a/3760193/1237974中的@Jon Skeets解决方案。对于大型项目的可维护性,我可能会使用Jons解决方案。

#11


0  

Another brute force solution could be,

另一个蛮力解决方案是,

    String input = "thequickbrownfoxjumps";
    int n = input.length()/4;
    String[] num = new String[n];

    for(int i = 0, x=0, y=4; i<n; i++){
    num[i]  = input.substring(x,y);
    x += 4;
    y += 4;
    System.out.println(num[i]);
    }

Where the code just steps through the string with substrings

在哪里,代码只是通过带有子字符串的字符串进行处理

#12


0  

    import static java.lang.System.exit;
   import java.util.Scanner;
   import Java.util.Arrays.*;


 public class string123 {

public static void main(String[] args) {


  Scanner sc=new Scanner(System.in);
    System.out.println("Enter String");
    String r=sc.nextLine();
    String[] s=new String[10];
    int len=r.length();
       System.out.println("Enter length Of Sub-string");
    int l=sc.nextInt();
    int last;
    int f=0;
    for(int i=0;;i++){
        last=(f+l);
            if((last)>=len) last=len;
        s[i]=r.substring(f,last);
     // System.out.println(s[i]);

      if (last==len)break;
       f=(f+l);
    } 
    System.out.print(Arrays.tostring(s));
    }}

Result

结果

 Enter String
 Thequickbrownfoxjumps
 Enter length Of Sub-string
 4

 ["Theq","uick","brow","nfox","jump","s"]

#13


0  

@Test
public void regexSplit() {
    String source = "Thequickbrownfoxjumps";
    // define matcher, any char, min length 1, max length 4
    Matcher matcher = Pattern.compile(".{1,4}").matcher(source);
    List<String> result = new ArrayList<>();
    while (matcher.find()) {
        result.add(source.substring(matcher.start(), matcher.end()));
    }
    String[] expected = {"Theq", "uick", "brow", "nfox", "jump", "s"};
    assertArrayEquals(result.toArray(), expected);
}

#14


0  

Here is my version based on RegEx and Java 8 streams. Test included.

这是我基于RegEx和Java 8流的版本。测试包括在内。

public static List<String> splitString(String input, int splitSize) {
    Matcher matcher = Pattern.compile("(?:(.{" + splitSize + "}))+?").matcher(input);
    return matcher.results().map(MatchResult::group).collect(Collectors.toList());
}

@Test
public void shouldSplitStringToEqualLengthParts() {
    String anyValidString = "Split me equally!";
    String[] expectedTokens2 = {"Sp", "li", "t ", "me", " e", "qu", "al", "ly"};
    String[] expectedTokens3 = {"Spl", "it ", "me ", "equ", "all"};

    Assert.assertArrayEquals(expectedTokens2, splitString(anyValidString, 2).toArray());
    Assert.assertArrayEquals(expectedTokens3, splitString(anyValidString, 3).toArray());
}

#1


178  

Here's the regex one-liner version:

以下是regex单行版本:

System.out.println(Arrays.toString(
    "Thequickbrownfoxjumps".split("(?<=\\G.{4})")
));

\G is a zero-width assertion that matches the position where the previous match ended. If there was no previous match, it matches the beginning of the input, the same as \A. The enclosing lookbehind matches the position that's four characters along from the end of the last match.

\G是一个零宽度断言,它匹配上一场比赛结束的位置。如果没有以前的匹配,它匹配输入的开始,和\A一样。包含的lookbehind与最后一场比赛结束时的四个字符的位置匹配。

Both lookbehind and \G are advanced regex features, not supported by all flavors. Furthermore, \G is not implemented consistently across the flavors that do support it. This trick will work (for example) in Java, Perl, .NET and JGSoft, but not in PHP (PCRE), Ruby 1.9+ or TextMate (both Oniguruma). JavaScript's /y (sticky flag) isn't as flexible as \G, and couldn't be used this way even if JS did support lookbehind.

lookbehind和\G都是高级regex功能,并不是所有口味都支持。而且,\G并没有在支持它的口味上一致地实现。这个技巧可以在Java、Perl、. net和JGSoft中使用(例如),但不能在PHP (PCRE)、Ruby 1.9+或TextMate(两者都是Oniguruma)中使用。JavaScript /y(粘贴标记)没有\G那么灵活,即使JS支持lookbehind,也不能用这种方式。

I should mention that I don't necessarily recommend this solution if you have other options. The non-regex solutions in the other answers may be longer, but they're also self-documenting; this one's just about the opposite of that. ;)

我应该指出,如果您有其他的选择,我并不一定推荐这种解决方案。其他答案中的非regex解决方案可能更长,但它们也是自文档化的;这个和那个刚好相反。,)

Also, this doesn't work in Android, which doesn't support the use of \G in lookbehinds.

此外,这在Android中也不适用,Android不支持在后视镜中使用\G。

#2


107  

Well, it's fairly easy to do this by brute force:

这很容易用蛮力来做:

public static List<String> splitEqually(String text, int size) {
    // Give the list the right capacity to start with. You could use an array
    // instead if you wanted.
    List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);

    for (int start = 0; start < text.length(); start += size) {
        ret.add(text.substring(start, Math.min(text.length(), start + size)));
    }
    return ret;
}

I don't think it's really worth using a regex for this.

我不认为它真的值得使用regex。

EDIT: My reasoning for not using a regex:

编辑:我不使用regex的理由:

  • This doesn't use any of the real pattern matching of regexes. It's just counting.
  • 这并不使用regex的任何实际模式匹配。它只是计数。
  • I suspect the above will be more efficient, although in most cases it won't matter
  • 我怀疑上面的方法会更有效,尽管在大多数情况下这并不重要
  • If you need to use variable sizes in different places, you've either got repetition or a helper function to build the regex itself based on a parameter - ick.
  • 如果您需要在不同的地方使用可变大小,那么您要么得到了重复,要么得到了一个辅助函数,以基于参数- ick来构建regex本身。
  • The regex provided in another answer firstly didn't compile (invalid escaping), and then didn't work. My code worked first time. That's more a testament to the usability of regexes vs plain code, IMO.
  • 另一个答案中提供的regex首先没有编译(无效转义),然后没有工作。我的代码第一次运行。在我看来,这更证明了regexes和普通代码的可用性。

#3


60  

This is very easy with Google Guava:

用谷歌番石榴很容易:

for(final String token :
    Splitter
        .fixedLength(4)
        .split("Thequickbrownfoxjumps")){
    System.out.println(token);
}

Output:

输出:

Theq
uick
brow
nfox
jump
s

Or if you need the result as an array, you can use this code:

或者,如果您需要结果作为数组,您可以使用以下代码:

String[] tokens =
    Iterables.toArray(
        Splitter
            .fixedLength(4)
            .split("Thequickbrownfoxjumps"),
        String.class
    );

Reference:

参考:

Note: Splitter construction is shown inline above, but since Splitters are immutable and reusable, it's a good practice to store them in constants:

注意:Splitter结构在上面的内联显示,但是由于Splitters是不可变的和可重用的,所以最好将它们存储在常量中:

private static final Splitter FOUR_LETTERS = Splitter.fixedLength(4);

// more code

for(final String token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){
    System.out.println(token);
}

#4


11  

If you're using Google's guava general-purpose libraries (and quite honestly, any new Java project probably should be), this is insanely trivial with the Splitter class:

如果您正在使用谷歌的guava通用库(老实说,任何新的Java项目都应该是这样),那么对于Splitter类来说,这简直是小菜一碟:

for (String substring : Splitter.fixedLength(4).split(inputString)) {
    doSomethingWith(substring);
}

and that's it. Easy as!

就是这样。简单!

#5


6  

public static String[] split(String src, int len) {
    String[] result = new String[(int)Math.ceil((double)src.length()/(double)len)];
    for (int i=0; i<result.length; i++)
        result[i] = src.substring(i*len, Math.min(src.length(), (i+1)*len));
    return result;
}

#6


4  

public String[] splitInParts(String s, int partLength)
{
    int len = s.length();

    // Number of parts
    int nparts = (len + partLength - 1) / partLength;
    String parts[] = new String[nparts];

    // Break into parts
    int offset= 0;
    int i = 0;
    while (i < nparts)
    {
        parts[i] = s.substring(offset, Math.min(offset + partLength, len));
        offset += partLength;
        i++;
    }

    return parts;
}

#7


3  

You can use substring from String.class (handling exceptions) or from Apache lang commons (it handles exceptions for you)

可以使用字符串中的子字符串。类(处理异常)或Apache lang commons(它为您处理异常)

static String   substring(String str, int start, int end) 

Put it inside a loop and you are good to go.

把它放入一个循环中,你就可以开始了。

#8


2  

I'd rather this simple solution:

我宁愿要一个简单的解决办法:

String content = "Thequickbrownfoxjumps";
while(content.length() > 4) {
    System.out.println(content.substring(0, 4));
    content = content.substring(4);
}
System.out.println(content);

#9


1  

In case you want to split the string equally backwards, i.e. from right to left, for example, to split 1010001111 to [10, 1000, 1111], here's the code:

如果您想要将字符串平均向后拆分,例如,从右到左,将1010001111拆分为[10,1000,1111],下面是代码:

/**
 * @param s         the string to be split
 * @param subLen    length of the equal-length substrings.
 * @param backwards true if the splitting is from right to left, false otherwise
 * @return an array of equal-length substrings
 * @throws ArithmeticException: / by zero when subLen == 0
 */
public static String[] split(String s, int subLen, boolean backwards) {
    assert s != null;
    int groups = s.length() % subLen == 0 ? s.length() / subLen : s.length() / subLen + 1;
    String[] strs = new String[groups];
    if (backwards) {
        for (int i = 0; i < groups; i++) {
            int beginIndex = s.length() - subLen * (i + 1);
            int endIndex = beginIndex + subLen;
            if (beginIndex < 0)
                beginIndex = 0;
            strs[groups - i - 1] = s.substring(beginIndex, endIndex);
        }
    } else {
        for (int i = 0; i < groups; i++) {
            int beginIndex = subLen * i;
            int endIndex = beginIndex + subLen;
            if (endIndex > s.length())
                endIndex = s.length();
            strs[i] = s.substring(beginIndex, endIndex);
        }
    }
    return strs;
}

#10


0  

I asked @Alan Moore in a comment to the accepted solution how strings with newlines could be handled. He suggested using DOTALL.

我在接受的解决方案中询问@Alan Moore如何处理带有换行的字符串。他建议使用DOTALL。

Using his suggestion I created a small sample of how that works:

利用他的建议,我创建了一个小样本,它是如何工作的:

public void regexDotAllExample() throws UnsupportedEncodingException {
    final String input = "The\nquick\nbrown\r\nfox\rjumps";
    final String regex = "(?<=\\G.{4})";

    Pattern splitByLengthPattern;
    String[] split;

    splitByLengthPattern = Pattern.compile(regex);
    split = splitByLengthPattern.split(input);
    System.out.println("---- Without DOTALL ----");
    for (int i = 0; i < split.length; i++) {
        byte[] s = split[i].getBytes("utf-8");
        System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
    }
    /* Output is a single entry longer than the desired split size:
    ---- Without DOTALL ----
    [Idx: 0, length: 26] - [B@17cdc4a5
     */


    //DOTALL suggested in Alan Moores comment on SO: https://*.com/a/3761521/1237974
    splitByLengthPattern = Pattern.compile(regex, Pattern.DOTALL);
    split = splitByLengthPattern.split(input);
    System.out.println("---- With DOTALL ----");
    for (int i = 0; i < split.length; i++) {
        byte[] s = split[i].getBytes("utf-8");
        System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
    }
    /* Output is as desired 7 entries with each entry having a max length of 4:
    ---- With DOTALL ----
    [Idx: 0, length: 4] - [B@77b22abc
    [Idx: 1, length: 4] - [B@5213da08
    [Idx: 2, length: 4] - [B@154f6d51
    [Idx: 3, length: 4] - [B@1191ebc5
    [Idx: 4, length: 4] - [B@30ddb86
    [Idx: 5, length: 4] - [B@2c73bfb
    [Idx: 6, length: 2] - [B@6632dd29
     */

}

But I like @Jon Skeets solution in https://*.com/a/3760193/1237974 also. For maintainability in larger projects where not everyone are equally experienced in Regular expressions I would probably use Jons solution.

但是我也喜欢https://*.com/a/3760193/1237974中的@Jon Skeets解决方案。对于大型项目的可维护性,我可能会使用Jons解决方案。

#11


0  

Another brute force solution could be,

另一个蛮力解决方案是,

    String input = "thequickbrownfoxjumps";
    int n = input.length()/4;
    String[] num = new String[n];

    for(int i = 0, x=0, y=4; i<n; i++){
    num[i]  = input.substring(x,y);
    x += 4;
    y += 4;
    System.out.println(num[i]);
    }

Where the code just steps through the string with substrings

在哪里,代码只是通过带有子字符串的字符串进行处理

#12


0  

    import static java.lang.System.exit;
   import java.util.Scanner;
   import Java.util.Arrays.*;


 public class string123 {

public static void main(String[] args) {


  Scanner sc=new Scanner(System.in);
    System.out.println("Enter String");
    String r=sc.nextLine();
    String[] s=new String[10];
    int len=r.length();
       System.out.println("Enter length Of Sub-string");
    int l=sc.nextInt();
    int last;
    int f=0;
    for(int i=0;;i++){
        last=(f+l);
            if((last)>=len) last=len;
        s[i]=r.substring(f,last);
     // System.out.println(s[i]);

      if (last==len)break;
       f=(f+l);
    } 
    System.out.print(Arrays.tostring(s));
    }}

Result

结果

 Enter String
 Thequickbrownfoxjumps
 Enter length Of Sub-string
 4

 ["Theq","uick","brow","nfox","jump","s"]

#13


0  

@Test
public void regexSplit() {
    String source = "Thequickbrownfoxjumps";
    // define matcher, any char, min length 1, max length 4
    Matcher matcher = Pattern.compile(".{1,4}").matcher(source);
    List<String> result = new ArrayList<>();
    while (matcher.find()) {
        result.add(source.substring(matcher.start(), matcher.end()));
    }
    String[] expected = {"Theq", "uick", "brow", "nfox", "jump", "s"};
    assertArrayEquals(result.toArray(), expected);
}

#14


0  

Here is my version based on RegEx and Java 8 streams. Test included.

这是我基于RegEx和Java 8流的版本。测试包括在内。

public static List<String> splitString(String input, int splitSize) {
    Matcher matcher = Pattern.compile("(?:(.{" + splitSize + "}))+?").matcher(input);
    return matcher.results().map(MatchResult::group).collect(Collectors.toList());
}

@Test
public void shouldSplitStringToEqualLengthParts() {
    String anyValidString = "Split me equally!";
    String[] expectedTokens2 = {"Sp", "li", "t ", "me", " e", "qu", "al", "ly"};
    String[] expectedTokens3 = {"Spl", "it ", "me ", "equ", "all"};

    Assert.assertArrayEquals(expectedTokens2, splitString(anyValidString, 2).toArray());
    Assert.assertArrayEquals(expectedTokens3, splitString(anyValidString, 3).toArray());
}