やりたいこととしては"insert", "create", "drop"
という文字列のリストがあるとき、自然順序ではなく、自分の好きな順序でソートしたい。具体的に言うと、"drop", "create", "insert"
という順序にソートしたい。
この場合、集合の要素が限定されているため、SQLだと特性関数でcase
によるソートをすれば良い。同じようなことをjavaでもやりたい。
環境
java 1.8
コード
特性関数をMapで持つ
特性関数に相当するものをMap
で持つ。keyが集合の要素でvalueがソート順序の整数。
Map<String, Integer> map = new HashMap<>();
map.put("drop", 1);
map.put("create", 2);
map.put("insert", 3);
List<String> list = Arrays.asList("insert", "create", "drop");
list.stream()
.sorted((s1, s2) -> map.get(s1).compareTo(map.get(s2)))
.forEach(System.out::println);
出力結果。
drop
create
insert
ファイル名を任意の順番でソート
これが必要になった状況としては、ある特定の順序でファイルをソートしたかった。たとえば、こんな感じのファイル群があるとする。
0001_create.sql
0001_drop.sql
0001_insert.sql
0002_create.sql
0002_drop.sql
0002_insert.sql
prefixの順番+suffixは前述の[drop -> create -> insert]、という順番でファイル一覧を取得したかった。
というわけでソースコード。
Map<String, Integer> map = new HashMap<>();
map.put("drop.sql", 1);
map.put("create.sql", 2);
map.put("insert.sql", 3);
Files.walk(Paths.get("files"))
.filter(Files::isRegularFile)
.sorted((p1, p2) -> {
String[] sp1 = p1.getFileName().toString().split("_");
String[] sp2 = p2.getFileName().toString().split("_");
String pp1 = sp1[0] + map.get(sp1[1]);
String pp2 = sp2[0] + map.get(sp2[1]);
return pp1.compareTo(pp2);})
.forEach(System.out::println);
出力結果。
files\0001_drop.sql
files\0001_create.sql
files\0001_insert.sql
files\0002_drop.sql
files\0002_create.sql
files\0002_insert.sql
といってもやることはそんな変わんない。ファイル名をセパレータで区切って、suffix部分を特性関数的なmapでソート順序の整数に変換。それをprefixの順番にくっつけると、"00013", "00012", "00011"
という文字列になるので、あとはcompareTo
するだけ。