CSVをソート (複数列指定)
ComparatorChain便利だった。
適当なライブラリを使ってCSVを読み込んでフィールドを文字列のリストにして、
それをさらに行数分リストにしたのを用意してソートする。
package demo; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.apache.commons.collections.comparators.ComparatorChain; /** CSVデータソート用クラス */ public final class CSVSort { /** * CSVをソートします * @param csv csvデータ * @param metaDatas ソート情報 */ @SuppressWarnings("unchecked") public static void sort(List<List<String>> csv, List<SortMetaData> metaDatas) { if (metaDatas.isEmpty()) { return; } // ソート情報をキー順に並べ替え Collections.sort(metaDatas, new Comparator<SortMetaData>() { @Override public int compare(SortMetaData o1, SortMetaData o2) { return (o1.order < o2.order ? -1 : (o1.order == o2.order ? 0 : 1)); } }); ComparatorChain cc = new ComparatorChain(); for (final SortMetaData meta : metaDatas) { cc.addComparator(new Comparator<List<String>>() { @Override public int compare(List<String> o1, List<String> o2) { return o1.get(meta.colNo).compareTo(o2.get(meta.colNo)); } }, !meta.isAscending); } // ソート Collections.sort(csv, cc); } /** ソート情報 */ public static class SortMetaData { /** 列番号 */ public final int colNo; /** キー順(何番目に有効にするか) */ public final long order; /** 昇順の場合{@code true} */ public final boolean isAscending; /** * コンストラクタ * @param colNos 列番号 * @param order キー順 * @param isAccending 昇順の場合{@code true} */ public SortMetaData(int colNos, long order, boolean isAccending) { this.colNo = colNos; this.order = order; this.isAscending = isAccending; } } }
testコード
package demo; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junit.framework.TestCase; import demo.CSVSort.SortMetaData; public class CSVSortTest extends TestCase { private static List<String> r(String... strings) { return Arrays.asList(strings); } private static String d(List<List<String>> csv) { StringBuilder sb = new StringBuilder(); for (List<String> line : csv) { for (String field : line) { sb.append(field); sb.append(','); } sb.deleteCharAt(sb.length() - 1); sb.append('\n'); } return sb.toString(); } /** sort test */ public void testSort() { List<List<String>> act = new ArrayList<List<String>>(); // r()は文字列配列をリストにするメソッド act.add(r("100", "120", "110")); act.add(r("100", "110", "120")); act.add(r("200", "100", "200")); List<SortMetaData> metaList = new ArrayList<SortMetaData>(); metaList.add(new SortMetaData(0, 1, false)); metaList.add(new SortMetaData(1, 1, true)); CSVSort.sort(act, metaList); List<List<String>> exp = new ArrayList<List<String>>(); exp.add(r("200", "100", "200")); exp.add(r("100", "110", "120")); exp.add(r("100", "120", "110")); // d()はオブジェクトをダンプするメソッド assertEquals(d(exp), d(act)); System.out.println(d(exp)); } }