Java – listchangelistener waspermutated block
The Javadoc of listchangelistener provides a template for handling changes But I don't know how to deal with permutations For each index, I can find the location of the new index of the item, but I don't know how to deal with it This is a difficult problem independent of programming language Observablelist can only add (), remove (), set (), and an iterator
If I have an original list [1,2,3] and bind list [] to it, the bound list [1,3] needs to match it If the comparator of the original list is swapped and the original list now reads [3,1], how can I make the bound list follow?
/** * Binds a source list's elements to a destination list. Any changes made in * the source list will reflect in the destination list. * * @param <SRC> The source list's object type. * @param <DEST> The destination list's object type. * @param dest The destination list that will be bound to the src list. * @param src The source list to watch for changes,and propagate up to the * destination list. * @param transformer A function that will transform a source list data * type,A,into a destination list data type,B. */ public static <SRC,DEST> void bindLists( ObservableList<DEST> dest,ObservableList<SRC> src,Function<? super SRC,? extends DEST> transformer) { /*Add the initial data into the destination list.*/ for (SRC a : src) { dest.add(transformer.apply(a)); } /*Watch for future data to add to the destination list. Also watch for removal of data form the source list to remove its respective item in the destination list.*/ src.addListener((Listchangelistener.Change<? extends SRC> c) -> { while (c.next()) { if (c.wasPermutated()) { /*How do you handle permutations? Do you remove and then add,or add and then remove,or use set,or use a copy arraylist and set the right indices? Removing/adding causes concurrent modifications.*/ for (int oldIndex = c.getFrom(); oldIndex < c.getTo(); oldIndex++) { int newIndex = c.getPermutation(oldIndex); dest.remove(oldIndex); dest.add(newIndex,dest.get(oldIndex)); } } else if (c.wasUpdated()) { } else { /*Respond to removed data.*/ for (SRC item : c.getRemoved()) { int from = c.getFrom(); dest.remove(from); } /*Respond to added data.*/ for (SRC item : c.getAddedSubList()) { int indexAdded = src.indexOf(item); dest.add(indexAdded,transformer.apply(item)); } } } }); }
Solution
For the permutation case, I'm not going to try to handle it with add () and remove () This will lead to index shifts and confusion (at least for me)
Conceptually, you get a series of affected elements and an array of numbers that represent the moving position of each element I think you understand In your code,
newIndex = getPermutation(oldIndex);
This means that the element to be at oldindex needs to be moved to newindex Wrinkles are that if you move directly, you may overwrite elements that have not been moved I think the easiest way to solve this problem is to make a copy of the affected sub range, and then step through the array and move the elements in the copy to a new position The code to do this is:
int from = c.getFrom(); int to = c.getTo(); List<DEST> copy = new ArrayList<>(dest.subList(from,to)); for (int oldIndex = from; oldIndex < to; oldIndex++) { int newIndex = c.getPermutation(oldIndex); dest.set(newIndex,copy.get(oldIndex - from)); }
This is an arrangement, so each element ends somewhere without adding or deleting any elements This means that you do not have to copy the list range, and you can move elements one at a time after moving the chain while using only a single temporary space element There may be more than one chain loop, so you must detect and process it It sounds complicated I'll leave it to another respondent.: -) For my money, copying the affected area is easy to understand
Normal list operation does not trigger the change mode of arrangement and update If you look at JavaFX collections. Observable listbase, you can see the list implementation protocol that can be used to build specific change information If the implementation provides the correct information to the nextpermutation or nextupdate methods, it will trigger these more other change patterns I'm not sure what might trigger them in JavaFX For example, a node that changes the stacking order of nodes Tofront() and node The Toback () method may generate permutation changes, but they don't seem to I don't know anything that will cause updates and changes
Semantically, I think the update change means that the elements within the list have changed, but the length of the list remains the same This is in contrast to the "replace" change pattern, in which a series of elements may be replaced by a different number of elements It may also be that the update change means that the element itself has not been replaced - that is, the contents of the list have not changed - but the internal state of the element has changed