• 追加された行はこの色です。
  • 削除された行はこの色です。
---
category: swing
folder: SortableTable
title: JTableのソート
tags: [JTable, JTableHeader]
author: aterai
pubdate: 2004-01-05
description: JTableのカラムヘッダをクリックすることで、行表示を降順、昇順にソートします。
image: https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTTXXYDR5I/AAAAAAAAAkQ/DeBHN6piDhQ/s800/SortableTable.png
---
* 概要 [#summary]
`JTable`のカラムヘッダをクリックすることで、行表示を降順、昇順にソートします。以下のサンプルは、%%[http://www2.gol.com/users/tame/swing/examples/JTableExamples5.html SortableTableExample]%%を参考にして作成しています。

#download(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTTXXYDR5I/AAAAAAAAAkQ/DeBHN6piDhQ/s800/SortableTable.png)

* サンプルコード [#sourcecode]
#code(link){{
class SortableTableModel extends DefaultTableModel {
  public SortableTableModel(String[] str, int row) {
    super(str, row);
  }

  public void sortByColumn(int column, boolean isAscent) {
    Collections.sort(getDataVector(), new ColumnComparator(column, isAscent));
    fireTableDataChanged();
  }
}
class ColumnComparator implements Comparator {
  final protected int index;
  final protected boolean ascending;
  public ColumnComparator(int index, boolean ascending) {

class ColumnComparator implements Comparator<Object>, Serializable {
  private static final long serialVersionUID = 1L;
  protected final int index;
  protected final boolean ascending;

  protected ColumnComparator(int index, boolean ascending) {
    this.index = index;
    this.ascending = ascending;
  }
  public int compare(Object one, Object two) {
    if (one instanceof Vector && two instanceof Vector) {
      Object oOne = ((Vector) one).elementAt(index);
      Object oTwo = ((Vector) two).elementAt(index);
      if (oOne == null && oTwo == null) {
        return 0;
      } else if (oOne == null) {
        return ascending ? -1 :  1;
      } else if (oTwo == null) {
        return ascending ?  1 : -1;
      } else if (oOne instanceof Comparable && oTwo instanceof Comparable) {
        Comparable cOne = (Comparable) oOne;
        Comparable cTwo = (Comparable) oTwo;
        return ascending ? cOne.compareTo(cTwo) : cTwo.compareTo(cOne);
      }

  @SuppressWarnings("unchecked")
  @Override public int compare(Object one, Object two) {
    if (one instanceof List && two instanceof List) {
      Comparable<Object> o1 = (Comparable<Object>) ((List<Object>) one).get(index);
      Comparable<Object> o2 = (Comparable<Object>) ((List<Object>) two).get(index);
      int c = Objects.compare(
          o1, o2, Comparator.nullsFirst(Comparator.<Comparable<Object>>naturalOrder()));
      return c * (ascending ? 1 : -1);
    }
    return 1;
  }
  public int compare(Number o1, Number o2) {
    double n1 = o1.doubleValue();
    double n2 = o2.doubleValue();
    if (n1 < n2) {
      return -1;
    } else if (n1 > n2) {
      return 1;
    } else {
      return 0;
    }
  }
    return 0;
}
}}

* 解説 [#explanation]
上記のサンプルでは、カラムヘッダをクリックすることでソートできます。右クリックからポップアップメニューで、行を追加、削除したり、セルをダブルクリックして中身を色々編集するなどしてソートを試してみてください。
上記のサンプルでは、各カラムヘッダのクリックでソート可能になっています。

- メモ
-- 複数の列をキーにしてソートしたい場合は、[[TableSorterでJTableをソート>Swing/TableSorter]]を参照
-- `JDK 1.6.0`で、`JTable`のソートが標準機能として追加された
--- [[TableRowSorterでJTableのソート>Swing/TableRowSorter]]
- 複数の列をキーにしてソートしたい場合は`TableSorter.java`が利用可能
-- [[TableSorterでJTableをソート>Swing/TableSorter]]
- `JDK 1.6.0`から`JTable`のソートが標準機能として追加された
-- [[TableRowSorterでJTableのソート>Swing/TableRowSorter]]

* 参考リンク [#reference]
- %%[http://www2.gol.com/users/tame/swing/examples/JTableExamples5.html SortableTableExample]%%
- [http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting Sorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)]
- [https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting Sorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)]

* コメント [#comment]
#comment
- 非常に参考になりました。すぐに実装に使わせていただきます。 -- &user(akio); &new{2005-01-12 18:11:14 (水)};
- カラムをドラッグして移動したとき、矢印が残ってしまうようです。 %%元からだったかデグレードしたのかちょっと不明です。%% 元からのようです。 -- &user(aterai); &new{2005-02-25 19:55:01 (金)};
- カラムをドラッグして移動したとき、矢印が残ってしまうようです。 %%元からかデグレードしたのかちょっと不明です。%% 元からのようです。 -- &user(aterai); &new{2005-02-25 19:55:01 (金)};
- 修正できたかな? %%確認中。%% 確認済み。 -- &user(aterai); &new{2005-02-25 20:30:57 (金)};
- `Swing`初心者の為このサイトのソースを参考に勉強させて頂いています。 -- &user(ao); &new{2005-03-11 14:37:03 (金)};
- 行を削除した後にソートを降順ソート、昇順ソート、初期状態と3回ソートを行うと削除した行が元に戻ってしまうようです。`TestModel.java`の`removeRow`に`list.remove(index);`を追加したらうまくいきましたが、本当にこれでよいのでしょうか?-- [[ao]] &new{2005-03-11 14:40:10 (金)};
- 行を削除した後にソートを降順ソート、昇順ソート、初期状態と3回ソートを行うと削除した行が元に戻ってしまうようです。`TestModel.java`の`removeRow`に`list.remove(index);`を追加したらうまくいきましたが、本当にこれでよいのでしょうか? -- &user(ao); &new{2005-03-11 14:40:10 (金)};
- %%いいと思います。バグなので修正しておきますm(_ _m)。%% あ、ダメみたいです。以下のように行番号をキーにして削除しないとソート中は別の行を削除してしまいます。 -- &user(aterai); &new{2005-03-11 19:13:45 (金)};

#code{{
public void removeRow(int index) {
  Integer num = (Integer) getValueAt(index, 0);
  Test test = (Test) list.elementAt(num.intValue() - 1);
  list.removeElement(test);
  super.removeRow(index);
}
}}

- 初期状態に戻すのを止めたほうがいいかもしれません(エクスプローラも初期状態に戻したりしないし)。わざわざ`Vector`で`list`を別に持つ必要も、キーとして番号の列を作る必要もなくなります。 -- &user(aterai); &new{2005-03-11 19:23:16 (金)};
- こちらのサンプルでは初期状態に戻すのを止めてみました。初期状態戻し有りにしたい場合は、[[TableSorterでJTableをソート>Swing/TableSorter]]の方を参考にしてみてください。 -- &user(aterai); &new{2005-03-11 21:08:34 (金)};
- ありがとうございます! -- &user(G); &new{2012-07-12 (木) 14:05:48};
-- どうもです。関係ない話ですが、元サンプル(`SortableTableExample`)が公開されているところを探してリンクを修正する予定です。 -- &user(aterai); &new{2012-07-13 (金) 17:35:04};

#comment