@Override
	protected void sort(List<BundleStatus> data, TableSortingContext<BundleStatus> sortingContext) {
		// notify accesses listeners, must be done on swing thread
		SystemUtilities.assertThisIsTheSwingThread("Must be called on the Swing thread");

		if (sortingContext.isUnsorted()) {
			// this is the 'no sort' state
			sortCompleted(sortingContext);
			notifyModelSorted(false);
			return;
		}

		hasEverSorted = true; // signal that we have sorted at least one time

		// wrap the assigned comparator to detect if the order changes

		AtomicBoolean changed = new AtomicBoolean(false);
		Comparator<BundleStatus> wrapper = new Comparator<>() {
			Comparator<BundleStatus> comparator = sortingContext.getComparator();

			@Override
			public int compare(BundleStatus o1, BundleStatus o2) {
				int result = comparator.compare(o1, o2);
				if (result < 0) {
					changed.set(true);
				}
				return result;
			}
		};
		Collections.sort(data, wrapper);
		sortCompleted(sortingContext);
		if (changed.get()) {
			notifyModelSorted(false);
		}
	}
overridden to avoid generating events when nothing changed
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusTableModel.java