Issue Description
The problem is known: you need to tokenize a string that may contain consecutive separators you need to keep as a single item in the resulting string list/array.
Splitting with lookaround(s) cannot help here, because an unanchored lookaround tests each position inside the string. If your pattern matched any char in the string, you could use \G operator, but it is not the case. Even adding a + quantifier - s0.split("(?=(?:&[A-Fa-fK-Ok-or0-9])+)" would still return &4, &lof as separate tokens because of this.
Solution
Use matching rather than splitting, and use building blocks to keep it readable.
String s0 = "This is a text&aThis is a test &bstring that &ehas plenty &4&lof &7colors.";
String colorRx = "&[A-Fa-fK-Ok-or0-9]";
String nonColorRx = "[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*";
Pattern pattern = Pattern.compile("(?:" + colorRx + ")+" + nonColorRx + "|" + nonColorRx);
Matcher m = pattern.matcher(s0);
List<String> res = new ArrayList<>();
while (m.find()){
if (!m.group(0).isEmpty()) res.add(m.group(0)); // Add if non-empty!
}
System.out.println(res);
// => [This is a text, &aThis is a test , &bstring that , &ehas plenty , &4&lof , &7colors.]
The regex is
(?:&[A-Fa-fK-Ok-or0-9])+[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*|[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*
See the regex demo here. It is actually based on your initial pattern: first, we match all the color codes (1 or more sequences), and then we match 0+ characters that are not a starting point for the color sequence (i.e. all strings other than the color codes). The [^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)* subpattern is a synonym of (?s)(?:(?!&[A-Fa-fK-Ok-or0-9]).)* and it is quite handy when you need to match some chunk of text other than the one you specify, but as it is resource consuming (especially in Java), the unrolled version is preferable.
So, the pattern - (?:" + colorRx + ")+" + nonColorRx + "|" + nonColorRx - matches 1+ colorRx subpatterns followed with optional nonColorRx subpatterns, OR (|) zero or more nonColorRx subpatterns. The .group(0).isEmpy() does not allow empty strings in the resulting array.
(?i)(?=&[a-fk-o0-9])(?<!&[a-fk-o0-9]). In other words, split on any color code that's not preceded by a color code.