Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过操纵可观察列表来引发置换事件?_Java_Javafx_Observablelist - Fatal编程技术网

Java 如何通过操纵可观察列表来引发置换事件?

Java 如何通过操纵可观察列表来引发置换事件?,java,javafx,observablelist,Java,Javafx,Observablelist,侦听器可以接收具有排列集的事件 同时,在列表操作中,我只看到要删除或插入元素的操作 是否可以对列表执行这样的操作,这将导致报告置换 更新 以下是澄清代码: public class ObservableListPermutation { public static void main(String[] args) { ObservableList<String> list = FXCollections.observableArrayList();

侦听器可以接收具有排列集的事件

同时,在列表操作中,我只看到要删除或插入元素的操作

是否可以对列表执行这样的操作,这将导致报告置换

更新

以下是澄清代码:

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


如果我尝试使用调试器跟踪排序,我将无法输入排序代码。

一个非常简单的操作是对列表中的项目进行排序

例如,下面的代码将打印为true

对补充问题的答复:


我想自己做,而不调用黑盒方法。假设我有一个ObservableList实例,仅此而已,并且想编写一些操作代码,这会导致排列,我将如何做到这一点

如果您使用FXCollections util类提供的ObservableList,这是不可能的,因为ObservableList是在其中实现的

考虑到以下几点:

无论何时添加或删除图元,都会触发

检查getPermutation返回的int数组的长度是否大于零

在MappingChange的情况下,始终返回长度为0的int

现在,你一定像我一样想知道,当我们在同一个列表上排序时,它是如何工作的

事实证明,它是在FXCollections中创建列表的基础,会覆盖列表,然后强制执行

还有别的选择吗


您可以通过扩展来创建自己的自定义ObservableList,如所述和所示。

要详细说明@ItachiUchiha的答案和@fabian的评论,任何修改ObservableList的操作都会通知更改侦听器。因此,无法通过调用一系列操作来触发ObservableList上的置换事件,每个操作都会修改列表,每个操作都会独立地通知侦听器

因此,要支持现成不支持的置换,即、、和,您需要实现自己的ObservableList,定义或可能重写触发置换的单个入口点方法。提供了一个方便的起点

下面是一个简单的例子:

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

}

我想到的最简单的排列是列表元素的排序。或者,我猜,shuffle也会导致这些事件:假设我想编写自己版本的shuffle。如果我在其中使用remove和add,我将永远不会导致排列。对于更新2中的注释,如果您试图了解Collections.sortlist的作用,它只会调用list.sortnull,请参阅。从FXCollections.observableArrayList返回的列表是非公共API的一个实例,它覆盖了sort以很好地管理事件。那么,sort如何导致这些事件呢?对ObservableList进行排序时,列表中的元素排列会发生变化。这将触发对ListChangeListener的通知。我希望自己触发它,而不调用黑盒方法。假设我有ObservalElist实例,仅此而已,并且想编写一些操作代码,这会导致排列,我该如何做呢?一般来说,FXCollections.sort应该优先于Collections.sort,但在这里它没有什么区别@造成事件本身的暗度有点棘手,因为在大多数情况下,这些事件的触发是自动处理的。最好的选择是手动扩展和触发事件。
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);
    }
}