我有自己的ObservableList
实施名为ObservableImmutableList
。它使用ImmutableList
接口包装了一个Guava ObservableList
,因此我可以使用JavaFX轻松地充分利用ImmutableList
。没有什么可变的,除了它允许使用ImmutableList
方法将另一个set()
作为支持列表交换(并通知所有更改的侦听器/绑定)。
但是,one problem I ran into is the ObservableImmutableList
cannot be sorted.我无法扩展或实施SortedList
,那么如何将其实现到此类中呢?
我尝试创建一个方法asSorted
(),它返回ObservableImmutableList
中包含的SortedList
。但它也行不通。是否有某种简单的抽象层可用于保持列表不可变但允许值在抽象层中使用?
public final class ObservableImmutableList<T> implements ObservableList<T> {
private volatile ImmutableList<T> backingList;
private final LazyProperty<SortedList<T>> sortedList = LazyProperty.forSupplier(() -> new SortedList<>(this));
private final CopyOnWriteArrayList<ListChangeListener<? super T>> listeners = new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<InvalidationListener> invalidationListeners = new CopyOnWriteArrayList<>();
private final ObjectProperty<ObservableList<T>> property;
private ObservableImmutableList(ImmutableList<T> immutableList) {
this.backingList = immutableList;
this.property = new SimpleObjectProperty<ObservableList<T>>(this);
}
public static <T> ObservableImmutableList<T> of(ImmutableList<T> immutableList) {
return new ObservableImmutableList<T>(immutableList);
}
public SortedList<T> asSorted() {
return sortedList.get();
}
public void set(ImmutableList<T> immutableList) {
this.property.setValue(this);
final ImmutableList<T> oldList = this.backingList;
final ImmutableList<T> newList = immutableList;
listeners.forEach(l -> l.onChanged(new Change<T>(this) {
private int changeNum = 0;
@Override
public boolean next() {
changeNum++;
return changeNum <= 2 ? true : false;
}
@Override
public boolean wasUpdated() {
return true;
}
@Override
public void reset() {
// TODO Auto-generated method stub
}
@Override
public int getFrom() {
return 0;
}
@Override
public int getTo() {
return changeNum == 1 ? oldList.size() - 1 : newList.size() - 1;
}
@Override
public List<T> getRemoved() {
return changeNum == 1 ? oldList : ImmutableList.of();
}
@Override
public List<T> getAddedSubList() {
return changeNum == 1 ? ImmutableList.of() : newList;
}
@Override
protected int[] getPermutation() {
int[] permutations = new int[changeNum == 1 ? oldList.size() : newList.size()];
for (int i = 0; i < permutations.length; i++) {
permutations[i] = i;
}
return permutations;
}
}));
this.backingList = immutableList;
invalidationListeners.forEach(l -> l.invalidated(this));
}
public ImmutableList<T> get() {
return backingList;
}
public ObjectProperty<ObservableList<T>> asProperty() {
return property;
}
@Override
public int size() {
return backingList.size();
}
@Override
public boolean isEmpty() {
return backingList.isEmpty();
}
@Override
public boolean contains(Object o) {
return backingList.contains(o);
}
@Override
public Iterator<T> iterator() {
return backingList.iterator();
}
@Override
public Object[] toArray() {
return backingList.toArray();
}
@Override
public <B> B[] toArray(B[] a) {
return backingList.toArray(a);
}
@Override @Deprecated
public boolean add(T e) {
return backingList.add(e);
}
@Override @Deprecated
public boolean remove(Object o) {
return backingList.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return backingList.containsAll(c);
}
@Override @Deprecated
public boolean addAll(Collection<? extends T> c) {
return backingList.addAll(c);
}
@Override @Deprecated
public boolean addAll(int index, Collection<? extends T> c) {
return backingList.addAll(index, c);
}
@Override @Deprecated
public boolean removeAll(Collection<?> c) {
return backingList.removeAll(c);
}
@Override @Deprecated
public boolean retainAll(Collection<?> c) {
return backingList.retainAll(c);
}
@Override @Deprecated
public void clear() {
backingList.clear();
}
@Override
public T get(int index) {
return backingList.get(index);
}
@Override @Deprecated
public T set(int index, T element) {
return backingList.set(index, element);
}
@Override @Deprecated
public void add(int index, T element) {
backingList.add(index, element);
}
@Override @Deprecated
public T remove(int index) {
return backingList.remove(index);
}
@Override
public int indexOf(Object o) {
return backingList.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return backingList.lastIndexOf(o);
}
@Override
public ListIterator<T> listIterator() {
return backingList.listIterator();
}
@Override
public ListIterator<T> listIterator(int index) {
return backingList.listIterator(index);
}
@Override
public ImmutableList<T> subList(int fromIndex, int toIndex) {
return backingList.subList(fromIndex, toIndex);
}
@Override
public void addListener(InvalidationListener listener) {
invalidationListeners.add(listener);
}
@Override
public void removeListener(InvalidationListener listener) {
invalidationListeners.remove(listener);
}
@Override
public void addListener(ListChangeListener<? super T> listener) {
listeners.add(listener);
}
@Override
public void removeListener(ListChangeListener<? super T> listener) {
listeners.remove(listener);
}
@Override @Deprecated
public boolean addAll(T... elements) {
return backingList.addAll(ImmutableList.copyOf(elements));
}
@Override @Deprecated
public boolean setAll(T... elements) {
return false;
}
@Override @Deprecated
public boolean setAll(Collection<? extends T> col) {
return false;
}
@Override @Deprecated
public boolean removeAll(T... elements) {
return backingList.removeAll(ImmutableList.copyOf(elements));
}
@Override @Deprecated
public boolean retainAll(T... elements) {
return false;
}
@Override @Deprecated
public void remove(int from, int to) {
}
@Override
public String toString() {
return backingList.toString();
}
}
答案 0 :(得分:4)
您询问的部分:SortedList只是其支持列表的包装器,它不会以任何方式更改它。因此,您可以将任何列表(可变或不可变)包装到SortedList中,并在TableView中使用它。在上一个问题的示例中:
ObservableList<NumericCombo> immutable =
FXCollections.unmodifiableObservableList(values);
// new ImmutableObservableList<>(values);
TableView<NumericCombo> tableView = new TableView<>();
SortedList sorted = new SortedList(immutable);
tableView.setItems(sorted);
sorted.comparatorProperty().bind(tableView.comparatorProperty());
您没有询问的部分(如何正确获取通知)。
一个简单的例子:
public class ImmutableObservableList<E> extends ObservableListBase<E> {
private List<E> backing;
public ImmutableObservableList(List<E> backingList) {
this.backing = backingList;
}
public void setBackingList(List<E> backingList) {
beginChange();
if (this.backing != null) {
nextRemove(0, this.backing);
}
this.backing = backingList;
if (backingList != null) {
nextAdd(0, backingList.size());
}
endChange();
}
@Override
public E get(int index) {
if (backing == null) throw new IndexOutOfBoundsException();
return backing.get(index);
}
@Override
public int size() {
return backing != null ? backing.size() : 0;
}
}