ListChangeListener wasPermutated块 [英] ListChangeListener wasPermutated block

查看:159
本文介绍了ListChangeListener wasPermutated块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ListChangeListener的JavaDoc提供了一个用于处理更改的模板。但是,我不知道如何处理排列。对于每个索引,我都可以找到项目的新索引所在的位置,但我不知道如何处理它。这是一个独立于编程语言的难题。 ObservableList只能添加(),remove(),set(),还有一个迭代器。

The JavaDoc for the ListChangeListener provides a template for handling changes. I don't know how to handle permutations, however. For every index, I can find out where the new index of the item is, but I don't know what to do with it. This is a bit of a puzzle that is independent of programming language. An ObservableList can only add(), remove(), set(), and also has an iterator.

如果我有原始列表[1,2,3] ,并将list []绑定到它,绑定列表[1,2,3]需要匹配它。
如果原始列表的比较器被交换,原始列表现在读取[3,2,1],我如何使绑定列表跟随?

If I have an original list [1,2,3], and bind a list[] to it, the bound list[1,2,3] needs to match it. If the original list gets its comparator swapped so that the original list now reads [3,2,1], how do I make the bound list follow along?

/**
 * 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));
                }
            }
        }
    });
}


推荐答案

对于排列情况,我我不打算尝试使用 add() remove()来处理它。这将导致索引转移并使事情混乱(至少对我而言)。

For the permutation case, I wouldn't bother trying to use add() and remove() to do handle it. This will cause the indexes to shift around and will make things confusing (at least to me).

从概念上讲,你得到的是一系列受影响的元素,以及一个包含数组一些数字表示每个元素的移动位置。我想你明白了。在您的代码中,

Conceptually what you get is a range of elements affected, and an array containing some numbers that indicate where each element was moved. I think you understand that much. In your code you have,

    newIndex = getPermutation(oldIndex);

这意味着该元素位于 oldIndex 需要移动到 newIndex 。皱纹是,如果你直接进行移动,你可能会覆盖尚未移动的元素。我认为处理这个问题最简单的方法是复制受影响的子范围,然后单步执行置换数组并将复制中的元素移动到新的位置。执行此操作的代码是:

which means that the element was at oldIndex needs to be moved to newIndex. The wrinkle is that if you just make the move directly, you might be overwriting an element that hasn't been moved yet. I think the simplest way to deal with this is to make a copy of the affected subrange and then just step through the permutation array and move elements from the copy into their new positions. 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 a permutation, so every element ends up somewhere, and none are added or deleted. This implies that you don't have to copy the list range, and that you could move elements one at a time following the chain of moves while using only a single element of temporary space. There might be multiple cycles of chains, so you'd have to detect and handle that too. That sounds pretty complex. I'll leave that for another answerer. :-) For my money, copying the affected range is simple and easy to understand.

排列和更新的更改模式不是由正常的列表操作触发的。如果查看 javafx.collections.ObservableListBase ,您可以看到列表实现可用于构建特定更改信息的协议。如果实现向 nextPermutation nextUpdate 方法提供正确的信息,它将触发这些更多其他更改模式。我不确定在JavaFX中可能触发它们的是什么。例如,更改节点堆叠顺序的 Node.toFront() Node.toBack()方法可能会生成排列变化,但似乎没有。我不知道会产生更新更改的任何内容。

The permutation and updated change modes aren't triggered by normal list actions. If you look at javafx.collections.ObservableListBase you can see a protocol that a list implementation can use to build up information about a specific change. If the implementation supplies the right information to nextPermutation or nextUpdate methods, it will trigger these more other change modes. I'm not sure what might trigger them in JavaFX. For example, the Node.toFront() and Node.toBack() methods to change node stacking order potentially could generate permutation changes, but they don't seem to. I don't know of anything that would generate an update change either.

从语义上讲,我认为更新更改意味着列表范围内的元素已更改,但列表的长度保持不变。这与替换更改模式形成对比,其中一系列元素可能被替换为不同数量的元素。也可能是更新更改意味着元素本身没有被替换 - 也就是说,列表内容没有改变 - 只是元素的内部状态已经改变。

Semantically, I think an update change implies that the elements in that range of the list have changed but that the length of the list stays the same. This is in contrast to the "replaced" change mode, where a range of elements might be replaced with a different number of elements. It could also be that the update change means that the elements themselves haven't been replaced -- that is, the list contents haven't changed -- merely that the elements' internal states have changed.

这篇关于ListChangeListener wasPermutated块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆