Swing/FastRemoveOfListItems のバックアップ(No.1)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/FastRemoveOfListItems へ行く。
- 1 (2018-03-19 (月) 16:24:28)
- 2 (2018-03-23 (金) 21:04:52)
- 3 (2018-04-26 (木) 16:48:23)
- 4 (2018-04-30 (月) 18:15:19)
- 5 (2020-04-23 (木) 18:40:05)
- 6 (2021-10-27 (水) 00:02:07)
- 7 (2023-09-09 (土) 19:11:24)
- 8 (2025-01-03 (金) 08:57:02)
- 9 (2025-01-03 (金) 09:01:23)
- 10 (2025-01-03 (金) 09:02:38)
- 11 (2025-01-03 (金) 09:03:21)
- 12 (2025-01-03 (金) 09:04:02)
- 13 (2025-06-19 (木) 12:41:37)
- 14 (2025-06-19 (木) 12:43:47)
- category: swing folder: FastRemoveOfListItems title: JListからの大量アイテム削除を高速化する tags: [JList, ListModel, AbstractListModel, DefaultListModel, SpringLayout] author: aterai pubdate: 2018-03-19T16:16:24+09:00 description: JListのListModelからの大量のアイテムを高速に削除する方法をテストします。 image: https://drive.google.com/uc?id=1w4uURJH6pPCGk68BT_XlCjxnZQlOxv1n7w
概要
JListのListModelからの大量のアイテムを高速に削除する方法をテストします。
Screenshot

Advertisement
サンプルコード
private static <E> void move1(JList<E> from, JList<E> to) {
ListSelectionModel sm = from.getSelectionModel();
int[] selectedIndices = from.getSelectedIndices();
DefaultListModel<E> fromModel = (DefaultListModel<E>) from.getModel();
DefaultListModel<E> toModel = (DefaultListModel<E>) to.getModel();
List<E> unselectedValues = new ArrayList<>();
for (int i = 0; i < fromModel.getSize(); i++) {
if (!sm.isSelectedIndex(i)) {
unselectedValues.add(fromModel.getElementAt(i));
}
}
if (selectedIndices.length > 0) {
for (int i : selectedIndices) {
toModel.addElement(fromModel.get(i));
}
fromModel.clear();
unselectedValues.forEach(fromModel::addElement);
}
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、大量のアイテムをもつJListを左右に配置し、選択アイテムを>、<ボタンで移動するテストを行っています。
default remove- 移動元の
JListで選択されているアイテムのインデックスをJList#getSelectedIndices()メソッドで取得 - 上で取得したインデックス配列を
forでループし、移動元のDefaultListModelからget(idx)でアイテムを取得、これを移動先のDefaultListModelへaddElement(...)でコピー - 上で取得したインデックス配列を
forで末尾からループし、移動元のDefaultListModelからremove(idx)でアイテムを削除 DefaultListModel#remove(idx)内で実行されるAbstractListModel#fireIntervalRemoved(...)が遅いため、アイテムを大量に削除する場合非常に時間が掛かるDefaultListModel#removeAllElements()で全削除、JListの選択モードがListSelectionModel.MULTIPLE_INTERVAL_SELECTIONでDefaultListModel#removeRange(...)メソッドで範囲削除が可能な場合、AbstractListModel#fireIntervalRemoved(...)は最後に一回呼ばれるだけなので高速
- 移動元の
clear + addElement- 移動元の
JListで選択されていないアイテムを別のArrayListに保存 - 移動元の
JListの選択インデックス配列をforループで回して、移動元のDefaultListModelへaddElement(...)でコピー DefaultListModel#clear()で移動元のJListをクリア- 保存していた未選択アイテムリストから移動元の
JListにアイテムを復元 AbstractListModel#fireIntervalRemoved(...)はDefaultListModel#clear()で一回呼ばれるだけなので高速
- 移動元の
addAll + removeAbstractListModelを継承するリストモデルを作成DefaultListModelで使用しているVectorではなく、ArrayListをアイテムの保持に使用- 選択アイテムのインデックス配列を引数にしてまとめて削除を実行するメソッドを追加
AbstractListModel#fireIntervalRemoved(...)は最後に一回呼ばれるだけなので高速public void remove(int... selectedIndices) { if (selectedIndices.length > 0) { int max = selectedIndices.length - 1; for (int i = max; i >= 0; i--) { delegate.remove(selectedIndices[i]); } fireIntervalRemoved(this, selectedIndices[0], selectedIndices[max]); } }
- 左右の
JList、中央のJButtonの配置は、SpringLayoutを使用してレイアウト- SpringLayoutの使用
- 左右の
JList: 親パネルの幅の40% - 中央の
JButtonを縦に配置したBox.createVerticalBox(): 親パネルの幅の10%