code: public void valueChanged(ListSelectionEvent lse) {
          if (!lse.getValueIsAdjusting()) {
              removeListSelectionListener(this);
  
              // remember everything selected as a result of this action
              HashSet<Integer> newSelections = new HashSet<>();
              int size = getModel().getSize();
              for (int i = 0; i < size; i++) {
                  if (getSelectionModel().isSelectedIndex(i)) {
                      newSelections.add(i);
                  }
              }
  
              // turn on everything that was previously selected
              Iterator<Integer> it = selectionCache.iterator();
              while (it.hasNext()) {
                  int index = it.next();
                  getSelectionModel().addSelectionInterval(index, index);
              }
  
              // add or remove the delta
              it = newSelections.iterator();
              while (it.hasNext()) {
                  Integer nextInt = it.next();
                  int index = nextInt;
                  if (selectionCache.contains(nextInt)) {
                      getSelectionModel().removeSelectionInterval(index, index);
                  } else {
                      getSelectionModel().addSelectionInterval(index, index);
                  }
              }
  
              // save selections for next time
              selectionCache.clear();
              for (int i = 0; i < size; i++) {
                  if (getSelectionModel().isSelectedIndex(i)) {
                      selectionCache.add(i);
                  }
              }
  
              addListSelectionListener(this);
  
          }
      }
docs: ListSelectionListener implementation