Skip to content

Instantly share code, notes, and snippets.

@fuxingloh
Last active January 14, 2020 06:10
Show Gist options
  • Select an option

  • Save fuxingloh/d2cb8793b586a62545453f589cec5b9b to your computer and use it in GitHub Desktop.

Select an option

Save fuxingloh/d2cb8793b586a62545453f589cec5b9b to your computer and use it in GitHub Desktop.
Java regex string splitter that keeps the delimiter. Java string split with delimiter kept.
public class PatternSplit {
private final Pattern pattern;
/**
* @param pattern pattern for the splitter
*/
private PatternSplit(Pattern pattern) {
this.pattern = pattern;
}
/**
* @param input string input
* ` * @return List of result object
*/
public List<String> split(CharSequence input) {
return split(input, 0);
}
/**
* @param input string input
* @param limit limit
* @return List of result object
*/
public List<String> split(CharSequence input, int limit) {
return split(input, limit, s -> s).stream()
.map(o -> (String) o).collect(Collectors.toList());
}
/**
* @param input string input
* @param limit limit
* @param delimitMapper delimiter function for delimited value
* @return List of result object
*/
public List<Object> split(CharSequence input, int limit, DelimitMapper delimitMapper) {
return split(input, limit, s -> s, delimitMapper);
}
/**
* @param input string input
* @param limit limit
* @param splitMapper splitter function for split value
* @param delimitMapper delimiter function for delimited value
* @return List of result object
*/
public List<Object> split(CharSequence input, int limit, SplitMapper splitMapper, DelimitMapper delimitMapper) {
return split(input, limit, splitMapper, (Matcher matcher) ->
delimitMapper.apply(input.subSequence(matcher.start(), matcher.end()).toString())
);
}
/**
* @param input string input
* @param limit limit
* @param splitMapper splitter function for split value
* @param matchMapper delimiter function for delimited value
* @return List of result object
*/
public List<Object> split(CharSequence input, int limit, SplitMapper splitMapper, MatchMapper matchMapper) {
int index = 0;
boolean matchLimited = limit > 0;
List<Object> matchList = new ArrayList<>();
Matcher m = pattern.matcher(input);
// Add segments before each match found
while (m.find()) {
if (!matchLimited || matchList.size() < limit - 1) {
if (index == 0 && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
Object split = splitMapper.apply(input.subSequence(index, m.start()).toString());
if (split != null) matchList.add(split);
matchList.add(matchMapper.apply(m));
index = m.end();
} else if (matchList.size() == limit - 1) { // last one
Object split = splitMapper.apply(input.subSequence(index, m.start()).toString());
if (split != null) matchList.add(split);
matchList.add(matchMapper.apply(m));
index = m.end();
}
}
// If no match was found, return this
if (index == 0)
return Collections.singletonList(input.toString());
// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());
// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize - 1).equals(""))
resultSize--;
return matchList.subList(0, resultSize);
}
/**
* @param pattern regex string
* @param flags pattern flags
* @return PatternSplit
*/
public static PatternSplit compile(String pattern, int flags) {
return new PatternSplit(Pattern.compile(pattern, flags));
}
/**
* @param pattern regex string
* @return PatternSplit
*/
public static PatternSplit compile(String pattern) {
return new PatternSplit(Pattern.compile(pattern));
}
@FunctionalInterface
interface SplitMapper extends Function<String, Object> {
}
@FunctionalInterface
interface DelimitMapper extends Function<String, Object> {
}
@FunctionalInterface
interface MatchMapper extends Function<Matcher, Object> {
}
}
public static String[] split(Pattern pattern, CharSequence input, int limit) {
int index = 0;
boolean matchLimited = limit > 0;
ArrayList<String> matchList = new ArrayList<>();
Matcher m = pattern.matcher(input);
// Add segments before each match found
while (m.find()) {
if (!matchLimited || matchList.size() < limit - 1) {
if (index == 0 && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
String match = input.subSequence(index, m.start()).toString();
matchList.add(match);
matchList.add(input.subSequence(m.start(), m.end()).toString());
index = m.end();
} else if (matchList.size() == limit - 1) { // last one
String match = input.subSequence(index, input.length()).toString();
matchList.add(match);
matchList.add(input.subSequence(m.start(), m.end()).toString());
index = m.end();
}
}
// If no match was found, return this
if (index == 0)
return new String[]{input.toString()};
// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());
// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize - 1).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(0, resultSize).toArray(result);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment