ObservableList
听众可以通过置换集接收Change
个事件。
同时,在列表操作中,我只看到要删除或插入元素的那些。
是否可以在列表上执行此类操作,这将导致报告排列?
更新
以下是澄清代码:
public class ObservableListPermutation {
public static void main(String[] args) {
ObservableList<String> list = FXCollections.observableArrayList();
list.add("timbuktu");
list.add("timid");
list.addListener(new ListChangeListener<String>() {
@Override
public void onChanged(Change<? extends String> c) {
while(c.next()) {
if( c.wasPermutated() ) {
System.out.println("Was permutated");
}
}
}
});
System.out.println("Sorting by library:");
Collections.sort(list);
System.out.println("Sorting by own:");
Collections2.sort(list);
}
public static class Collections2 {
public static void sort(List<String> list) {
String element = list.remove(0);
list.add(element);
}
}
}
如您所见,我的自定义排列不会导致排列事件,因为它是通过删除和添加元素来完成的。如何实现自定义排列,以便导致排列事件?
更新2
如果我尝试使用调试器跟踪sort()
,我将无法输入sort()
的代码。
答案 0 :(得分:2)
一个非常简单的操作,List to report Permutation将对List中的项进行排序。
例如,以下代码将打印true
。
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.Collections;
public class PermutationTest {
public static void main(String[] args) {
ObservableList<String> list =
FXCollections.observableArrayList("Z", "Y", "X");
list.addListener(new ListChangeListener<String>() {
@Override
public void onChanged(Change<? extends String> c) {
c.next();
System.out.println(c.wasPermutated());
}
});
Collections.sort(list);
}
}
其他问题的答案:
我想自己做,不用黑盒子方法。假设我有ObservableList的实例,仅此而且想编写一些操作,这会导致排列,我该怎么做?
如果您使用FXCollections util类提供的 ObservableList,则无法实现,因为ObservableList的实现方式。
考虑以下几点:
每当您添加或删除元素时,都会触发MappingChange。
ListChangeListener#wasPermutated()检查getPermutation()
返回的int数组的长度是否大于零。
对于MappingChange,getPermuatation()始终返回长度为0的int。
现在,您一定想知道(就像我一样),当我们在同一个列表上进行排序时,它是如何工作的?
事实证明ObservableListWrapper(这是在FXCollections中创建列表的基础)会覆盖sort(),然后强制SimplePermutationChange。
有替代方案吗?
您可以按照ModifiableObservableListBase所述并this comment中显示的this answer扩展来创建您自己的自定义ObservableList。
答案 1 :(得分:1)
详细说明@ ItachiUchiha的回答和@ fabian的评论,修改ObservableList
的任何单个操作都将通知更改侦听器。因此,无法通过调用每个修改列表的操作序列来触发ObservableList
上的“置换事件”(每个操作都会独立地通知侦听器)。
因此,为了支持开箱即用(即FXCollections.sort()
,FXCollections.shuffle()
,FXCollections.rotate()
和FXCollections.reverse()
)不支持的排列,您需要实现自己的排列ObservableList
,定义(或可能覆盖)触发排列的单个入口点方法。 ModifiableObservableListBase
class提供了一个方便的起点。
这是一个简单的例子:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.collections.ModifiableObservableListBase;
public class PermutatingObservableList<E> extends ModifiableObservableListBase<E> {
private final List<E> source ;
public PermutatingObservableList(List<E> source) {
this.source = source ;
}
public void permute(int[] permutation) {
checkPermutation(permutation);
beginChange();
List<E> temp = new ArrayList<>(source);
for (int i = 0 ; i < size() ; i++) {
source.set(i, temp.get(permutation[i]));
}
nextPermutation(0, size(), permutation);
endChange();
}
public void pairwiseSwap() {
int[] permutation = new int[size()];
for (int i = 0; i+1 < permutation.length ; i+=2) {
permutation[i] = i+1 ;
permutation[i+1] = i ;
}
if (permutation.length % 2 == 1) {
permutation[permutation.length - 1] = permutation.length - 1 ;
}
permute(permutation);
}
private void checkPermutation(int[] permutation) {
boolean valid = permutation.length == size();
Set<Integer> values = IntStream.range(0, size()).boxed().collect(Collectors.toSet());
for (int i=0; i<permutation.length && valid ; i++) {
valid = values.remove(new Integer(permutation[i]));
}
if (! valid) {
throw new IllegalArgumentException("Invalid permuation: "+Arrays.toString(permutation)+"\n"
+"Permutation must be same length as list and must contain each of the values "
+ "0-"+(size()-1)+" exactly once");
}
}
@Override
public E get(int index) {
return source.get(index);
}
@Override
public int size() {
return source.size();
}
@Override
protected void doAdd(int index, E element) {
source.add(index, element);
}
@Override
protected E doSet(int index, E element) {
return source.set(index, element);
}
@Override
protected E doRemove(int index) {
return source.remove(index);
}
}
和测试:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.collections.ListChangeListener;
public class PermutingObservableListTest {
public static void main(String[] args) {
List<String> numbers = Arrays.asList("One", "Two", "Three", "Four", "Five");
PermutatingObservableList<String> list = new PermutatingObservableList<>(new ArrayList<>(numbers));
list.addListener(new ListChangeListener<String>() {
@Override
public void onChanged(Change<? extends String> c) {
while (c.next())
System.out.println(c.wasPermutated());
System.out.println(IntStream.range(0, list.size())
.map(c::getPermutation)
.mapToObj(Integer::toString)
.collect(Collectors.joining(", ")));
}
}
});
list.pairwiseSwap();
System.out.println(list);
}
}
产生输出
true
1, 0, 3, 2, 4
[Two, One, Four, Three, Five]