Я работаю над контурным сканером. Для каждого контура я хочу сохранить углы/края. Вместо того, чтобы иметь массив в контуре, у меня есть один большой массив, который я разделяю. Причиной этого является то, что он должен работать с анимацией, поэтому это для оптимизации.Как бороться с ConcurrentModificationException в этом случае
Идея заключается в том, что каждый контур get представляет собой подклассный вид большого массива.
я работала достаточно долго на одном классе, чтобы сделать это легко, и теперь я столкнулся с проблемой:
ArrayList<PVector> vecs = new ArrayList<PVector>();
for (int i = 0; i < 10; i++) {
vecs.add(new PVector());
}
List<PVector> subList = vecs.subList(0, 5);
for (int i = 0; i < 10; i++) {
vecs.add(new PVector());
}
// ConcurrentModificationException
for (int i = 0; i < subList.size(); i++) {
}
Во-первых, это плохой дизайн Java, что делает бросает одновременное изменение, если я использую add(Object)
? Это не должно влиять на какой-либо сублист, который у меня уже есть, так как он добавляет в конец право? (логическая речь). Моя точка зрения заключается в том, что add(Object)
никогда не может повлиять на уже существующий сублист, только add(index, Object)
может это сделать (и другие вещи, такие как удаление, своп и сортировка).
Второй. Что было бы хорошим способом справиться с этим? Я мог бы сделать большой массив действительно большим, так что менее вероятно, что мне нужно добавить элементы после того, как я уже сделал сублист, но мне интересно, есть ли какие-либо другие хорошие способы борьбы с ним.
Вот класс, я сделал, что должен был сделать его легким для меня, но делает мою жизнь трудно прямо сейчас :)
public class ListDivisor<T> {
List<T> list;
int subListStartIndex = 0;
int currentGetIndex = 0;
InstanceHelper instanceHelper;
public ListDivisor(List<T> list, InstanceHelper<T> instanceHelper) {
this.list = list;
this.instanceHelper = instanceHelper;
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public void reset() {
subListStartIndex = 0;
currentGetIndex = 0;
if (instanceHelper.doResetInstances()) {
for (T obj : list) {
instanceHelper.resetInstance(obj);
}
}
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public List<T> getSubList(int size) {
int fromIndex = subListStartIndex; // inclusive
int toIndex = fromIndex + size; // exclusive
for (int i = list.size(); i < toIndex; i++) {
list.add((T) instanceHelper.createInstance());
}
subListStartIndex = toIndex;
currentGetIndex = toIndex;
return list.subList(fromIndex, toIndex);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/**
* Returns a subList starting where the previous subList ended till
* the latest object added till then.
*
* @return
*/
public List<T> getSubList() {
return getSubList(currentGetIndex-subListStartIndex);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public T getNext() {
if (currentGetIndex >= list.size()) {
list.add((T)instanceHelper.createInstance());
}
return list.get(currentGetIndex++);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public void clear() {
list.clear();
reset();
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public interface InstanceHelper<T> {
public T createInstance();
public boolean doResetInstances();
public void resetInstance(T obj);
}
}
Это небольшой пример того, как использовать класс:
ListDivisor<PVector> vectorsDivisor = new ListDivisor<PVector>(
new ArrayList<PVector>(),
new InstanceHelper<PVector>() {
//@Override
public PVector createInstance() {
return new PVector();
}
//@Override
public boolean doResetInstances() {
return true;
}
//@Override
public void resetInstance(PVector v) {
v.set(0,0,0);
}
});
PVector v = vectorsDivisor.getNext();
v.set(1, 1, 1);
v = vectorsDivisor.getNext();
v.set(2, 2, 2);
v = vectorsDivisor.getNext();
v.set(3, 3, 3);
subList = vectorsDivisor.getSubList();
println("subList size: "+subList.size());
Вы знаете, вы могли бы просто сделать копию подписок, так что изменение оригинала не вызовет проблемы. –
Итак, ваша проблема в том, что использование подписок, возвращаемых 'getSubList'' listDivisor', вызывает «ConcurrentModificationException»? – Edward
@Edward - Yep - см. Http://stackoverflow.com/questions/27262602/possible-reason-for-concurrentmodificationexception –