Skip to content

Commit

Permalink
Enhancement: If there are a large number of elements, using replaceAl…
Browse files Browse the repository at this point in the history
…l may cause performance issues.
  • Loading branch information
leewyatt committed May 24, 2024
1 parent ccb1202 commit f47a5eb
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 26 deletions.
31 changes: 5 additions & 26 deletions gemsfx/src/main/java/com/dlsc/gemsfx/MultiColumnListView.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dlsc.gemsfx;

import com.dlsc.gemsfx.skins.MultiColumnListViewSkin;
import com.dlsc.gemsfx.util.ListUtils;
import javafx.beans.InvalidationListener;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ListProperty;
Expand Down Expand Up @@ -346,13 +347,7 @@ public ColumnListCell(MultiColumnListView<T> multiColumnListView) {

multiColumnListView.getDraggedItems().setAll(getListView().getSelectionModel().getSelectedItems());

getListView().getItems().replaceAll(item -> {
if (item == getItem()) {
return multiColumnListView.getPlaceholderFrom();
}

return item;
});
ListUtils.updateFirstMatching(getListView().getItems(), item -> item == getItem(), multiColumnListView.getPlaceholderFrom());
});

setOnDragOver(event -> {
Expand Down Expand Up @@ -395,13 +390,7 @@ public ColumnListCell(MultiColumnListView<T> multiColumnListView) {
items.remove(multiColumnListView.getPlaceholderFrom());

T draggedItem = multiColumnListView.getDraggedItem();
items.replaceAll(item -> {
if (item == multiColumnListView.getPlaceholderTo()) {
return draggedItem;
}

return item;
});
ListUtils.updateFirstMatching(items, item -> item == multiColumnListView.getPlaceholderTo(), draggedItem);

if (!items.contains(draggedItem)) {
// probably dropped on same list view / same column (hence no "to" placeholder)
Expand All @@ -423,24 +412,14 @@ public ColumnListCell(MultiColumnListView<T> multiColumnListView) {
getListView().getItems().removeIf(item -> item == multiColumnListView.getPlaceholderFrom());
} else {
log(" drop was not completed, replacing placeholder with dragged item");
getListView().getItems().replaceAll(item -> {
if (item == multiColumnListView.getPlaceholderFrom()) {
return multiColumnListView.getDraggedItem();
}
return item;
});
ListUtils.updateFirstMatching(getListView().getItems(), item -> item == multiColumnListView.getPlaceholderFrom(), multiColumnListView.getDraggedItem());
}
} else {
log("drag done, not accepted");

// put the item back into the "from" location
log("putting item back into 'from' location");
getListView().getItems().replaceAll(item -> {
if (item == multiColumnListView.getPlaceholderFrom()) {
return multiColumnListView.getDraggedItem();
}
return item;
});
ListUtils.updateFirstMatching(getListView().getItems(), item -> item == multiColumnListView.getPlaceholderFrom(), multiColumnListView.getDraggedItem());
}

multiColumnListView.setDraggedItem(null);
Expand Down
61 changes: 61 additions & 0 deletions gemsfx/src/main/java/com/dlsc/gemsfx/util/ListUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.dlsc.gemsfx.util;

import java.util.List;
import java.util.ListIterator;
import java.util.function.Predicate;

public class ListUtils {

/**
* Update matching elements in the list with the provided new value.
*
* @param list the list to operate on
* @param matchPredicate the predicate to match elements
* @param newValue the new value to replace matching elements
* @param breakAfterFirstMatch whether to break after the first match
* @param <T> the type of elements in the list
* @return the number of elements updated
*/
public static <T> int updateMatching(List<T> list, Predicate<T> matchPredicate, T newValue, boolean breakAfterFirstMatch) {
int updateCount = 0;
ListIterator<T> iterator = list.listIterator();
while (iterator.hasNext()) {
T currentElement = iterator.next();
if (matchPredicate.test(currentElement)) {
iterator.set(newValue);
updateCount++;
if (breakAfterFirstMatch) {
break;
}
}
}
return updateCount;
}

/**
* Update the first matching element in the list with the provided new value.
*
* @param list the list to operate on
* @param matchPredicate the predicate to match elements
* @param newValue the new value to replace matching elements
* @param <T> the type of elements in the list
* @return the number of elements updated
*/
public static <T> int updateFirstMatching(List<T> list, Predicate<T> matchPredicate, T newValue) {
return updateMatching(list, matchPredicate, newValue, true);
}

/**
* Update all matching elements in the list with the provided new value.
*
* @param list the list to operate on
* @param matchPredicate the predicate to match elements
* @param newValue the new value to replace matching elements
* @param <T> the type of elements in the list
* @return the number of elements updated
*/
public static <T> int updateAllMatching(List<T> list, Predicate<T> matchPredicate, T newValue) {
return updateMatching(list, matchPredicate, newValue, false);
}
}

0 comments on commit f47a5eb

Please sign in to comment.