152

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

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

Similar Question:

Split string into equal-length substrings in Scala

Community
  • 1
  • 1
Emil
  • 13,577
  • 18
  • 69
  • 108

23 Answers23

272

Here's the regex one-liner version:

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.

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.

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

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

Alan Moore
  • 73,866
  • 12
  • 100
  • 156
  • 2
    In PHP 5.2.4 works following code: return preg_split('/(?<=\G.{'.$len.'})/u', $str,-1,PREG_SPLIT_NO_EMPTY); – Igor Mar 23 '12 at 14:50
  • Nice answer. Which regexes support the \G flag? – Cris Stringfellow Dec 20 '12 at 06:35
  • 10
    For the record, using `String.substring()` instead of a regex, while requiring a few extra lines of code, will run somewhere on the order of 5x faster... – drew moore Sep 23 '14 at 14:17
  • 2
    In Java this does not work for a string with newlines. It will only check up to the first newline, and if that newline happens to be before the split-size, then the string will not be split. Or have I missed something? – joensson Nov 11 '14 at 22:58
  • @joensson: You're right, I was assuming there would be no newlines. I think that's reasonable given the lack of any other whitespace in the sample string. And newlines complicate things more than you might expect. You can add the DOTALL modifier, but the results will vary depending on what style of newline (`\n`, `\r\n`, `\r`) you use in the string, what style is used by your command line, whether you've set your IDE or editor to convert them automatically, et al. – Alan Moore Nov 12 '14 at 05:26
  • @AlanMoore I agree that in this case there will be no newlines. My comment was just as much a notice to others wanting to use the regex for other purposes - and to know if there was some magic setting I could apply to the regex for it to handle newlines. The DOTALL was what I was looking for. – joensson Nov 13 '14 at 08:40
  • "the other answers may be longer, but they're also self-documenting; this one's just about the opposite of that" -- not unless you include a link to this answer – Dexygen Aug 07 '15 at 14:59
  • 6
    For the sake of completeness: splitting text over multilines needs a prefixed `(?s)` in the regex: `(?s)(?<=\\G.{4})`. – bobbel Mar 29 '16 at 10:26
  • 1
    Java barfs on this completely at compile-time: `java.util.regex.PatternSyntaxException: Look-behind pattern matches must have a bounded maximum length` – Jeffrey Blattman May 04 '16 at 22:46
  • @JeffreyBlattman: What's your configuration? I've tested this regex in every Java version from 4 to 8, using the reference implementation's `javac` and `java` commands. In fact, I've tried changing the quantifier to `{4,}`, which is *supposed* to throw that exception, but it still works. How did you manage it? – Alan Moore May 05 '16 at 04:41
  • 1
    @JeffreyBlattman: Ah, that's it! Android uses the ICU regex library, which seems to have a problem with `\G` in lookbehinds. Here's [another question](http://stackoverflow.com/q/29603616/20938) about it, though I disagree with the analysis in the accepted answer. ICU was explicitly designed to copy the syntax and semantics of Java's regex flavor, but apparently they got that detail wrong. – Alan Moore May 05 '16 at 17:33
  • 2
    @JeffreyBlattman I doubt that you got the exception *at compile time*… – Holger Sep 20 '19 at 12:49
  • @bobbel I need a help on this regular expression. I am using this expression (?s)(?<=\\G.{4}) to split a multi line sentence into fixed length sentences. But this breaks words. Can we modify this to avoid breaking of words in between? – Moble Joseph Jul 07 '20 at 07:41
  • @MobleJoseph: you could try something like `.{0,30}[^ ](?= )` which splits the text on maximal 30 chars. If there is no space at this position, it takes less chars and splits. – bobbel Jul 07 '20 at 11:17
  • Does not work with all Unicode characters. Try an input where we replace the `q` with FACE WITH MEDICAL MASK: `"Theuickbrownfoxjumps"` yields: `[Theuickbrownfoxjumps]` (fails to split). – Basil Bourque Apr 15 '21 at 22:22
  • This is accepted answer, and has 267 upvotes, but it wont work in all cases. – H.A.H. Sep 12 '22 at 08:37
160

Well, it's fairly easy to do this with simple arithmetic and string operations:

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

Note: this assumes a 1:1 mapping of UTF-16 code unit (char, effectively) with "character". That assumption breaks down for characters outside the Basic Multilingual Plane, such as emoji, and (depending on how you want to count things) combining characters.

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

EDIT: My reasoning for not using a regex:

  • This doesn't use any of the real pattern matching of regexes. It's just counting.
  • 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.
  • 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.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @Jon Skeet : Thanks for clearing it but i didn't get your point. "I don't think it's really worth using a regex for this" – jmj Sep 21 '10 at 12:23
  • Why isn't it worth using a regex? I'm not disagreeing with you I'm just wondering if its more cost or readability etc. – Gage Sep 21 '10 at 12:24
  • @org.life.java: Well what's the benefit of using a regex here? You're not really matching patterns as such... you're just getting the substrings blindly. It doesn't seem a good fit for regular expressions to me. – Jon Skeet Sep 21 '10 at 12:25
  • @Jon:I asked for regex since i can split the string in just one statement. – Emil Sep 21 '10 at 12:28
  • Agree, but if its just for smaller strings and its not often then we should go for this i would say. – jmj Sep 21 '10 at 12:29
  • 11
    @Emil: Actually, you *didn't* ask for a regex. It's in the tags, but nothing in the question itself asks for a regex. You put this method in one place, and then you can split the string in just one *very readable* statement anywhere in your code. – Jon Skeet Sep 21 '10 at 12:31
  • @Jon:i'm accepting your answer.If possible please append a regex version too along with the answer. – Emil Sep 21 '10 at 12:36
  • 3
    Emil this is not what a regex is for. Period. – Chris Sep 21 '10 at 12:43
  • 4
    @Emil: If you want a one-liner for splitting the string, I'd recommend Guava's `Splitter.fixedLength(4)` as suggested by seanizer. – ColinD Sep 21 '10 at 13:43
  • Also, please show an answer that uses XML, and an answer that uses the SimpleDateFormat class. :-) Seriously, some tools just aren't useful for a problem. You might be able to put screws in with a hammer, but wouldn't it make more sense to use a screwdriver? That's what it's for. – Jay Sep 21 '10 at 14:00
  • 3
    @Jay:come-on you need not be that sarcastic.I'm sure it can be done using regex in just one-line.A fixed length sub-string is also a pattern.What do you say about this answer. http://stackoverflow.com/questions/3760152/split-string-of-equal-lengths-in-java/3761521#3761521 . – Emil Sep 21 '10 at 15:16
  • 5
    @Emil: I didn't intend that to be rude, just whimsical. The serious part of my point was that while yes, I'm sure you could come up with a Regex to do this -- I see Alan Moore has one that he claims works -- it is cryptic and therefore difficult for a later programmer to understand and maintain. A substring solution can be intuitive and readable. See Jon Skeet's 4th bullet: I agree with that 100%. – Jay Sep 21 '10 at 18:53
  • This has me wondering: would it be more efficient to convert to a char array and mod on size? I mean substring is doing a fair amount of counting. Just a thought. – javamonkey79 Oct 20 '10 at 17:23
  • @javamonkey79: What kind of counting are you thinking about? – Jon Skeet Oct 20 '10 at 18:03
  • @Jon: I assumed too much about the implementation of the String class. It doesn't do any counting in order to perform substring as I expected but rather "knows" the indices of the underlying array. – javamonkey79 Oct 27 '10 at 19:59
  • 2
    @JonSkeet I wouldn’t call this solution “brute force”, as it doesn’t do anything worse than other solutions. In fact, it calculates the substring boundaries directly, whereas the regex solution will actually iterate over the characters, to find a “match” at the intended positions. So if any of the posted solutions is “brute force”, it’s the regex variant. – Holger Sep 20 '19 at 12:57
  • Does not work with all Unicode characters. Try an input where we replace the `q` with FACE WITH MEDICAL MASK: `"Theuickbrownfoxjumps"` yields: ret = [The?, ?uic, kbro, wnfo, xjum, ps] – Basil Bourque Apr 15 '21 at 22:25
  • @BasilBourque: Thanks, I'll add a note to that in the limitations. – Jon Skeet Apr 16 '21 at 06:13
80

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:

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

// more code

for(final String token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){
    System.out.println(token);
}
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • 1
    Thanks for the post(For making me aware of guava library method).But i'll have to accept the regex answer http://stackoverflow.com/questions/3760152/split-string-of-equal-lengths-in-java/3761521#3761521 since it doesn't require any 3rd party library and a one-liner. – Emil Sep 21 '10 at 15:31
  • 1
    Including hundreds of KB of library code just to perform this simple task is almost certainly not the right thing. – Jeffrey Blattman May 04 '16 at 22:46
  • 2
    @JeffreyBlattman including Guava just for this is probably overkill, true. But I use it as a general-purpose library in all my Java code anyway, so why not use this one additional piece of functionality – Sean Patrick Floyd Jan 26 '17 at 14:38
  • any way to join back with a separator? – Aquarius Power May 02 '17 at 05:49
  • 2
    @AquariusPower `String.join(separator, arrayOrCollection)` – Holger Sep 20 '19 at 12:58
  • Does not work with all Unicode characters. Try Guava 30.1.1 with an input where we replace the `q` with FACE WITH MEDICAL MASK: `"Theuickbrownfoxjumps"` yielding: The? ?uic kbro … – Basil Bourque Apr 15 '21 at 22:37
15

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:

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

and that's it. Easy as!

Cowan
  • 37,227
  • 11
  • 66
  • 65
  • Does not work with all Unicode characters. Try Guava 30.1.1 with an input where we replace the `q` with FACE WITH MEDICAL MASK: `"Theuickbrownfoxjumps"` yielding: The? ?uic kbro … – Basil Bourque Apr 15 '21 at 22:39
8
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;
}
Saul
  • 17,973
  • 8
  • 64
  • 88
  • Since `src.length()` and `len` are both `int`s, your call `ceiling` isn't accomplishing what you want--check out how some of the other responses are doing it: (src.length() + len - 1) / len – Michael Brewer-Davis Sep 21 '10 at 13:24
  • @Michael: Good point. I didn't test it with strings of non-multiple lengths. It's fixed now. – Saul Sep 21 '10 at 13:50
6
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;
}
Grodriguez
  • 21,501
  • 10
  • 63
  • 107
5

Here's a one-liner version which uses Java 8 IntStream to determine the indexes of the slice beginnings:

String x = "Thequickbrownfoxjumps";

String[] result = IntStream
                    .iterate(0, i -> i + 4)
                    .limit((int) Math.ceil(x.length() / 4.0))
                    .mapToObj(i ->
                        x.substring(i, Math.min(i + 4, x.length())
                    )
                    .toArray(String[]::new);
Marko Previsic
  • 1,820
  • 16
  • 30
3

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);
Cheetah Coder
  • 149
  • 2
  • 5
  • 1
    Don't do this! String is immutable so your code needs to copy the whole remaining string every 4 characters. Your snippet therefore takes quadratic rather than linear time in the size of the String. – Tobias Sep 01 '16 at 14:59
  • @Tobias: Even if String was mutable, this snippet does the mentioned redundant copy, except there be complex compile processes concerning it. The only reason for using this snippet is code simplicity. – Cheetah Coder Sep 21 '16 at 05:46
  • Did you change your code since you first posted it? The latest version doesn't actually make copies - substring() runs efficiently (constant time, at least on old versions of Java); it keeps a reference to the entire string's char[] (at least on old versions of Java), but that's fine in this case since you're keeping all the characters. So the latest code that you have here is actually okay (modulo that your code prints an empty line if content starts as the empty string, which may not be what one intends). – Tobias Sep 25 '16 at 22:12
  • @Tobias: I don't remember any change. – Cheetah Coder Dec 17 '16 at 06:46
  • 1
    @Tobias the `substring` implementation changed with Java 7, update 6 in the middle of 2012, when the `offset` and `count` fields were removed from the `String` class. So the complexity of `substring` turned to linear long before this answer was made. But for a small string like the example, it still runs fast enough and for longer strings…well this task rarely occurs in practice. – Holger Sep 20 '19 at 15:25
3

A StringBuilder version:

public static List<String> getChunks(String s, int chunkSize)
{
 List<String> chunks = new ArrayList<>();
 StringBuilder sb = new StringBuilder(s);

while(!(sb.length() ==0)) 
{           
   chunks.add(sb.substring(0, chunkSize));
   sb.delete(0, chunkSize);

}
return chunks;

}

FSm
  • 2,017
  • 7
  • 29
  • 55
2

i use the following java 8 solution:

public static List<String> splitString(final String string, final int chunkSize) {
  final int numberOfChunks = (string.length() + chunkSize - 1) / chunkSize;
  return IntStream.range(0, numberOfChunks)
                  .mapToObj(index -> string.substring(index * chunkSize, Math.min((index + 1) * chunkSize, string.length())))
                  .collect(toList());
}
rloeffel
  • 144
  • 7
1

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

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

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

pakore
  • 11,395
  • 12
  • 43
  • 62
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:

/**
 * @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;
}
Joseph Tesfaye
  • 814
  • 14
  • 26
1

Here is a one liner implementation using Java8 streams:

String input = "Thequickbrownfoxjumps";
final AtomicInteger atomicInteger = new AtomicInteger(0);
Collection<String> result = input.chars()
                                    .mapToObj(c -> String.valueOf((char)c) )
                                    .collect(Collectors.groupingBy(c -> atomicInteger.getAndIncrement() / 4
                                                                ,Collectors.joining()))
                                    .values();

It gives the following output:

[Theq, uick, brow, nfox, jump, s]
Pankaj Singhal
  • 15,283
  • 9
  • 47
  • 86
  • 3
    That’s a horrible solution, fighting the intend of the API, using stateful functions and being significantly more complicated than an ordinary loop, not to speak of the boxing and string concatenation overhead. If you want a Stream solution, use something like `String[] result = IntStream.range(0, (input.length()+3)/4) .mapToObj(i -> input.substring(i *= 4, Math.min(i + 4, input.length()))) .toArray(String[]::new);` – Holger Sep 20 '19 at 13:12
1

Java 8 solution (like this but a bit simpler):

public static List<String> partition(String string, int partSize) {
  List<String> parts = IntStream.range(0, string.length() / partSize)
    .mapToObj(i -> string.substring(i * partSize, (i + 1) * partSize))
    .collect(toList());
  if ((string.length() % partSize) != 0)
    parts.add(string.substring(string.length() / partSize * partSize));
  return parts;
}
Timofey Gorshkov
  • 4,987
  • 6
  • 41
  • 66
1

Use code points to handle all characters

Here is a solution:

  • Works with all 143,859 Unicode characters
  • Allows you to examine or manipulate each resulting string, if you have further logic to process.

To work with all Unicode characters, avoid the obsolete char type. And avoid char-based utilities. Instead, use code point integer numbers.

Call String#codePoints to get an IntStream object, a stream of int values. In the code below, we collect those int values into an array. Then we loop the array, for each integer we append the character assigned to that number to our StringBuilder object. Every nth character, we add a string to our master list, and empty the StringBuilder.

String input = "Thequickbrownfoxjumps";

int chunkSize = 4 ;
int[] codePoints = input.codePoints().toArray();  // `String#codePoints` returns an `IntStream`. Collect the elements of that stream into an array.
int initialCapacity = ( ( codePoints.length / chunkSize ) + 1 );
List < String > strings = new ArrayList <>( initialCapacity );

StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < codePoints.length ; i++ )
{
    sb.appendCodePoint( codePoints[ i ] );
    if ( 0 == ( ( i + 1 ) % chunkSize ) ) // Every nth code point.
    {
        strings.add( sb.toString() ); // Remember this iteration's value.
        sb.setLength( 0 ); // Clear the contents of the `StringBuilder` object.
    }
}
if ( sb.length() > 0 ) // If partial string leftover, save it too. Or not… just delete this `if` block.
{
    strings.add( sb.toString() ); // Remember last iteration's value.
}

System.out.println( "strings = " + strings );

strings = [Theq, uick, brow, nfox, jump, s]

This works with non-Latin characters. Here we replace q with FACE WITH MEDICAL MASK.

String text = "Theuickbrownfoxjumps"

strings = [The, uick, brow, nfox, jump, s]

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

Here is my version based on RegEx and Java 8 streams. It's worth to mention that Matcher.results() method is available since Java 9.

Test included.

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());
}
itachi
  • 3,389
  • 2
  • 24
  • 29
0

The simplest solution is:

  /**
   * Slices string by passed - in slice length.
   * If passed - in string is null or slice length less then 0 throws IllegalArgumentException.
   * @param toSlice string to slice
   * @param sliceLength slice length
   * @return List of slices
   */
  public static List<String> stringSlicer(String toSlice, int sliceLength) {
    if (toSlice == null) {
      throw new IllegalArgumentException("Passed - in string is null");
    }
    if (sliceLength < 0) {
      throw new IllegalArgumentException("Slice length can not be less then 0");
    }
    if (toSlice.isEmpty() || toSlice.length() <= sliceLength) {
      return List.of(toSlice);
    }
    
   return Arrays.stream(toSlice.split(String.format("(?s)(?<=\\G.{%d})", sliceLength))).collect(Collectors.toList());
  }
Jackkobec
  • 5,889
  • 34
  • 34
-1
    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"]
Ravichandra
  • 2,162
  • 4
  • 24
  • 36
-1

I asked @Alan Moore in a comment to the accepted solution how strings with newlines could be handled. He suggested using 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://stackoverflow.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://stackoverflow.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.

Community
  • 1
  • 1
joensson
  • 1,967
  • 1
  • 22
  • 18
-1

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

Hubbly
  • 1
  • 2
-1
@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);
}
-1
public static String[] split(String input, int length) throws IllegalArgumentException {

    if(length == 0 || input == null)
        return new String[0];

    int lengthD = length * 2;

    int size = input.length();
    if(size == 0)
        return new String[0];

    int rep = (int) Math.ceil(size * 1d / length);

    ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_16LE));

    String[] out = new String[rep];
    byte[]  buf = new byte[lengthD];

    int d = 0;
    for (int i = 0; i < rep; i++) {

        try {
            d = stream.read(buf);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(d != lengthD)
        {
            out[i] = new String(buf,0,d, StandardCharsets.UTF_16LE);
            continue;
        }

        out[i] = new String(buf, StandardCharsets.UTF_16LE);
    }
    return out;
}
User8461
  • 366
  • 2
  • 14
-1
public static List<String> getSplittedString(String stringtoSplit,
            int length) {

        List<String> returnStringList = new ArrayList<String>(
                (stringtoSplit.length() + length - 1) / length);

        for (int start = 0; start < stringtoSplit.length(); start += length) {
            returnStringList.add(stringtoSplit.substring(start,
                    Math.min(stringtoSplit.length(), start + length)));
        }

        return returnStringList;
    }
Raj Hirani
  • 182
  • 1
  • 5