方法 FXCollections.shuffle()
仅限火灾 wasRemoved
更改通知。我们可能知道,洗牌不仅仅是删除,而是删除和添加。
在文档中我们可以看到:
洗牌可观察列表中的所有元素。在列表上只触发一个更改通知。
如果我没弄错的话,一个单一的改变可以同时包含这两个方面 wasAdded
以及 wasRemoved
. 真可惜 wasPermutated
不是用默认值触发的 ObservableList
fxapi(或者是?)。
测试代码:
public class SimpleMain {
public static void main(String[] args) {
ObservableList<Integer> integers = FXCollections.observableArrayList(1, 2, 3, 4);
integers.addListener(initListener());
FXCollections.shuffle(integers);
}
private static ListChangeListener<Integer> initListener() {
return change -> {
while (change.next()) {
if (change.wasPermutated()) {
System.out.println("wasPermutated");
} else if (change.wasRemoved()) {
System.out.println("wasRemoved");
} else if (change.wasAdded()) {
System.out.println("wasAdded");
}
}
};
}
}
2条答案
按热度按时间hxzsmxv21#
我在while循环中向listchangelistener添加了一行:
我得到的结果是:
这暗示了你的错误。字符串表示中使用的动词是“replaced”。去掉侦听器中的'else's并为wasreplaced()添加一个检查,您将看到这正是您得到的结果。
7nbnzgx92#
问题
您的代码假定
wasAdded()
以及wasRemoved()
是相互排斥的,不管你是不是有意的。这种假设是错误的。如果替换了一个或多个连续元素,那么这两个方法都将返回true
.请记住
Change
对象和“更改”。单身汉Change
示例可以携带多个更改。当文件上说:在列表上只触发一个更改通知。
它不是说只有一个
Change
对象将被发送到ListChangeListener
. 它说的是Change
对象将只携带一个更改。换言之Change#next()
方法将只返回true
为了第一次的召唤while
循环将只循环一次。解决方案
你需要重写你的代码
wasAdded()
以及wasRemoved()
两者都可以true
. 例如,下面是一个侦听器,它检查所有类型的更改:以上用途
wasReplaced()
这和wasAdded() && wasRemoved()
. 注意,检查wasReplaced()
必须在任何一个之前发生wasRemoved()
或者wasAdded()
如果使用if-else-if结构。否则上面的代码将遇到与您的代码相同的问题。如果将上述内容插入代码并运行,您将看到以下输出:
文件
ListChangeListener.Change
给出了如何实现ListChangeListener
.注意文档中的示例不检查
wasReplaced()
明确地。相反,它在最终的else
块(后wasPermutated()
以及wasUpdated()
返回false
). 这是可能的,因为getRemoved()
以及getAddedSubList()
如果没有删除或添加元素,则返回空列表。如果处理任何删除的元素,然后再处理任何添加的元素,效果通常与特别处理替换的效果相同。但是,根据您的用例,专门处理替换可能是有益的。为什么不排列呢?
他们实施计划的方式
shuffle
方法是:来源:javafx.collections.fxcollections,javafx 15。
如您所见,元素被提取到一个数组中,数组被洗牌,然后列表中的元素被数组替换。这就导致了一个“替代变化”被炒鱿鱼。