先日書いた、CSV形式の1行分の文字列からList<String>への変換 - Oboe吹きプログラマの黙示録
を単純に、interface のメソッドにする。
import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Function; public interface Csvtolist extends Serializable{ public static Function<String, List<String>> of(){ return Csvtolist::create; } public static List<String> create(String str){ char DELIMITER = ','; char CARRIAGE_RETURN = '\r'; char NEWLINE = '\n'; char DOUBLE_QUOTE = '"'; if (str==null || str.length()==0){ return Collections.emptyList(); } List<String> tokens = new ArrayList<String>(); StringBuilder tokenBuf = new StringBuilder(); boolean insideDoubleQuote = false; boolean isDoubleQuoteEscapeActive = false; StringBuilder wspBuf = new StringBuilder(); for(int ii=0; ii < str.length(); ii++){ final char ch = str.charAt(ii); if (ch==CARRIAGE_RETURN || ch==NEWLINE){ if (insideDoubleQuote){ tokenBuf.append(ch); }else{ throw new RuntimeException("unquoted " + (ch=='\n' ? "newline" : "carriage return") + " found at position #" + (ii+1)); } }else if(ch==DOUBLE_QUOTE){ if (insideDoubleQuote){ if (isDoubleQuoteEscapeActive){ tokenBuf.append(ch); isDoubleQuoteEscapeActive = false; }else if(((ii+1) < str.length()) && str.charAt(ii+1)==DOUBLE_QUOTE){ isDoubleQuoteEscapeActive = true; }else{ insideDoubleQuote = false; } }else{ insideDoubleQuote = true; if (wspBuf.length() != 0){ if (tokenBuf.length() != 0){ tokenBuf.append(wspBuf); } wspBuf.delete(0, wspBuf.length()); } } }else{ if (insideDoubleQuote){ tokenBuf.append(ch); }else{ if (ch==DELIMITER){ tokens.add(tokenBuf.toString()); tokenBuf.delete(0, tokenBuf.length()); wspBuf.delete(0, wspBuf.length()); }else if(Character.isWhitespace(ch)){ wspBuf.append(ch); }else{ if (wspBuf.length() != 0){ if (tokenBuf.length() != 0){ tokenBuf.append(wspBuf); } wspBuf.delete(0, wspBuf.length()); } tokenBuf.append(ch); } } } } if (insideDoubleQuote){ throw new RuntimeException("terminating double quote not found"); } tokens.add(tokenBuf.toString()); return tokens; } }
of() で、Function<String, List<String>> を返すようにしているので、
Optional の map で使用できる。
List<String> list = Optional.ofNullable(str).map(Csvtolist.of()).orElse(List.of());
結局、以下のように書いても同じではあるけど。
List<String> list = Optional.ofNullable(str).map(Csvtolist::create).orElse(List.of());