escape がある区切り文字による split

String の split(String regex) は、頻繁に良く使われるメジャーなメソッドである。
でも、区切り文字(デリミタ)に対してエスケープがあり、エスケープ文字を考慮して split でリストを求めたい。
サンプル文字列
 「$.aaa.\.bb\.bbb.cc\.\.c.\.\ddd\..ee\\ee.f\f」
デリミタ '.' に対してエスケープする文字は、`\` のケース
splitして 改行して並べた結果、以下を期待する。

$
aaa
.bb.bbb
cc..c
.ddd.
ee\ee
ff

StringTokenizer で実行する方法
ただし、デリミタ、エスケープ文字はメソッド引数で指定できない

public static List<String> splittolist(String str){
   List<String> list = new ArrayList<>();
   StringTokenizer st = new StringTokenizer(str, ".", true);
   String s = "";
   while (st.hasMoreTokens()) {
      String c = st.nextToken();
      if (c.equals(".")) {
         if (s.endsWith("\\")){
            s += c;
         }else {
            list.add(s.replaceAll("\\\\", ""));
            s = "";
         }
      }else {
         s += c;
      }
   }
   list.add(s.replaceAll("\\\\", ""));
   return list;
}

StringTokenizer で実行する方法
デリミタ、エスケープ文字を指定できるようにする。

public static List<String> tokenToList(String str, char sep, char escape){
   List<String> list = new ArrayList<>();
   String sp = new String(new char[]{ sep });
   String escapes = new String(new char[]{ escape, escape });
   StringTokenizer st = new StringTokenizer(str, sp, true);
   String s = "";
   while (st.hasMoreTokens()){
      String c = st.nextToken();
      if (c.equals(sp)) {
         if (s.charAt(s.length()-1)==escape) {
            s += c;
         }else{
            list.add(s.replaceAll(escapes, ""));
            s = "";
         }
      }else {
         s += c;
      }
   }
   list.add(s.replaceAll(escapes, ""));
   return list;
}

char 型で処理する方法

public static List<String> tokenToList(String str, char sep, char escape){
   List<String> list = new ArrayList<>();
   StringBuilder sb = new StringBuilder();
   boolean isEscape = false;
   for(char c:str.toCharArray()) {
      if (isEscape) {
         isEscape = false;
      }else if(c==escape){
         isEscape = true;
         continue;
      }else if(c==sep){
         list.add(sb.toString());
         sb.setLength(0);
         continue;
      }
      sb.append(c);
   }
   list.add(sb.toString());
   return list;
}
String str = "$.aaa.\\.bb\\.bbb.cc\\.\\.c.\\.\\ddd\\..ee\\\\ee.f\\f";
List<String> list = tokenToList(str, '.', '\\');
list.stream().forEach(e->{
   System.out.println("["+e+"]");
});

上の結果

[$]
[aaa]
[.bb.bbb]
[cc..c]
[.ddd.]
[ee\ee]
[ff]