首先是我的对象:
public class Group {
private final ObservableList<IDevice> sourceList;
private final ObservableList<IDevice> destinationList;
private final ObservableList<Mapping> mappingList;
...}
public class Mapping {
private final IDevice source;
private final IDevice destination;
private final MappingMode mode;
public final StringProperty sourceName = new SimpleStringProperty();
public final StringProperty destinationName = new SimpleStringProperty();
public final StringProperty modeName = new SimpleStringProperty();
...}
基本上,一个组包含两个IDevices列表,它们可以是源或目标,也可以是包含其中一个和两种模式之一的映射列表(枚举)。
IDevice列表显示在一个自己的列表视图中,它们之间有一个表,表示映射(包含第一列中的一列,第二列中的一列和模式列)。
我已经通过setItems添加了它们,这是ListViews的CellFactory
private Callback<ListView<IDevice>, ListCell<IDevice>> getFullNameDisplay() {
return new Callback<ListView<IDevice>, ListCell<IDevice>>() {
@Override
public ListCell<IDevice> call(ListView<IDevice> p) {
ListCell<IDevice> cell = new ListCell<IDevice>() {
@Override
protected void updateItem(IDevice t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
setText(t.getFullName());
}
else
setText("");
}
};
return cell;
}
};
}
列设置如下:
sourceColumn.setCellValueFactory(cellData -> cellData.getValue().sourceName);
destinationColumn.setCellValueFactory(cellData -> cellData.getValue().destinationName);
modeColumn.setCellValueFactory(cellData -> cellData.getValue().modeName);
我为每个列表视图添加了两个按钮来添加和删除新项目。
当然,如果我删除源设备或目标设备,我希望删除所有映射,所以我将ListChangeListener添加到两个列表中:
private ListChangeListener<IDevice> getDeviceChangeListener() {
return (javafx.collections.ListChangeListener.Change<? extends IDevice> c) -> {
while (c.next()) {
if (c.wasRemoved()) {
c.getRemoved().stream().forEach((d) -> {
mappingList.stream().filter((map) -> (map.getSource().equals(d) || map.getDestination().equals(d))).forEach((map) -> {
mappingList.remove(map);
});
});
}
}
};
}
这也是我打算做的(以及我尝试过的所有重构),但我不知道为什么这会调用(大部分时间)ConcurrentModificationException,因为我还没有在我的应用程序中使用任何线程。它似乎每次都没有触发,我明白如果我要使用线程,我可以很幸运。虽然结果是正确的
有人知道吗?
提前致谢
答案 0 :(得分:2)
除非通过迭代器完成修改,否则在迭代时不能修改集合。在Java 8中,Collection
类引入了removeIf(...)
方法,该方法有助于此用例:
private ListChangeListener<IDevice> getDeviceChangeListener() {
return (javafx.collections.ListChangeListener.Change<? extends IDevice> c) -> {
while (c.next()) {
if (c.wasRemoved()) {
c.getRemoved().forEach(d ->
mappingList.removeIf(map -> map.getDestination().equals(d)
|| map.getSource().equals(d)));
}
}
};
}
答案 1 :(得分:1)
在同一个循环中,如果您尝试迭代同一个集合并尝试修改同一个集合,Java会抛出此并发异常。
如果您想修改该系列,请保留另一个系列以进行添加或修改。一旦它出现在循环中,请调用Collection.addAll()或Collection.removeAll()接口。