I know what a ConcurrentModificationException is. I had them before, I solved them before and I can get away with a Iterator.
However, In this case I don't understand why it's being thrown.
public boolean pointOnEdgeBlob(int x, int y, float edgeHitEpsilon) {
init();
for (int i = 0; i < nOfBlobs; i++) {
Blob b = blobs.get(i);
// >>>>>>>>>>>>>>>>>>>>> here it calls the method where it goes wrong
if (b.edgeHit(x, y, edgeHitEpsilon)) return true;
}
return false;
}
Here is the edgeHit method that it in the blob:
public boolean edgeHit(float x, float y, float edgeHitEpsilon) {
// quick test if it's worth it
if (x < getMinX()-edgeHitEpsilon || x > getMaxX()+edgeHitEpsilon || y < getMinY()-edgeHitEpsilon || y > getMaxY()+edgeHitEpsilon) {
return false;
}
// the last one should be connected to the first
// >>>>>>>>>>>>>>> if i comment the part in the for loop then this get's the problem.
PVector pre = cornerVectors.get(cornerVectors.size() -1);
PVector cur;
for (int i = 0; i < cornerVectors.size(); i++) {
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> on this line it throws
cur = cornerVectors.get(i);
if(Blob.onLine(pre, cur, x, y, edgeHitEpsilon)) {
return true;
}
pre = cur;
}
return false;
}
Update:
cornerVectors is a list view:
List<PVector> cornerVectors;
It get's set with:
list.subList(fromIndex, toIndex);
There are no other threats running.
Here is the stack trace:
Exception in thread "Animation Thread"
java.util.ConcurrentModificationException at
java.util.SubList.checkForComodification(AbstractList.java:752) at
java.util.SubList.size(AbstractList.java:625) at
nl.doekewartena.contour.scanner.Blob.edgeHit(Blob.java:229) at
nl.doekewartena.contour.scanner.BlobData.pointOnEdgeBlob(BlobData.java:333)
at
nl.doekewartena.contour.scanner.ContourFinder.scan(ContourFinder.java:555)
at
nl.doekewartena.contour.scanner.ContourFinder.scan(ContourFinder.java:469)
at exclude.T04_ContourFinder.draw(T04_ContourFinder.java:38) at
processing.core.PApplet.handleDraw(PApplet.java:2386) at
processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
at processing.core.PApplet.run(PApplet.java:2256) at
java.lang.Thread.run(Thread.java:695)
Once you do
x = list.subList(fromIndex, toIndex);
the list should not be modified or it will throw CME when accesing x
From the .subList javadocs:
The semantics of the list returned by this method become undefined if
the backing list (i.e., this list) is structurally modified in any way
other than via the returned list. (Structural modifications are those
that change the size of this list, or otherwise perturb it in such a
fashion that iterations in progress may yield incorrect results.)
Related
I have created this program where an array of bubble objects will be created in the constructor, and then the bubbles will float accross the canvas and once the bubbles touch each other they will disappear and reveal the words "POP!". My method called noneLeft() should return true if all the bubbles have been popped and then another method called redisplayAll() will be called and the bubbles will reset and redisplay again. However, I am not sure what to write for my if statement to return true once the last bubble has been popped. How do I write down if the last bubble in the array has been popped, then return true. Would I have to use bubbles.length?
public Mover(double width, double height, int numberOfBubbles) {
canvasWidth = width;
canvasHeight = height;
bubbles = new Bubble[numberOfBubbles];
for (int i = 0; i < numberOfBubbles; i ++){
bubbles[i] = new Bubble();
bubbles[i].showBubble(width, height);
}
count = 0;
}
public boolean noneLeft() {
if (bubbles[].isPopped() == true){
return true;
}
return false;
}
The code should be
public boolean noneLeft() {
for (Bubble b : bubbles) {
if (!b.isPopped()) {
return false;
}
}
return true;
}
Iterate over the bubbles and as soon as you find one that has not popped return false since at least one bubble is left.
To start things off, I am making a game. You fight on a 3x3 Grid (using a 2 Dimensional-Array), and if the "Lane#" (Lane# = Row + Col) ahead of you is blank then you get a -15% Damage Reduction, and this stacks for every blank lane.
This means if you are on [0][0] then you are in Lane# 0, and therefore, cannot possibly have anyone ahead of you, and you will always take 100% of Damage (this is of course without defense and yadda yadda else that modifies)
And if you are on [2][2] then you are in Lane# 4, and if every lane ahead of you has atleast one space in it taken, then you will take 15*4 = 60, 100-60 = 40% of actual damage.
Now that that is out of the way. I am having difficulty returning 0... I keep getting an Error that says that you cannot return a Void value...
'cannot return a value from method whose result type is void'
public Blanks(int l) { //l = Lane
int x = 0; //The Return
for (int i = 0; i < 6; i++) //The loop
if (l=0){ //Here I keep getting an error saying 'incompatible types'
x = 0;
return x; //Here is the 'cannot return a void value' error
break;
}
if (l>=1){
x++;
}
if (l>=2){
x++;
}
if (l>=3){
x++;
}
if (l>=4){
x++;
}
return x; //for some odd reason, this is also a void value
}
}
I still have yet to add the Checking the Array / Grid part as I am stumped about that one as well.. but another problem, another question.. the actual array itself..
you should modify the method header to public int Blanks(int l) {
and you should remove break; keyword because you return method value before it and will be unreached statement.
In order to return an integer value you have to mention a return type in the method. Also, in the first if statement you have used assignment operator instead of comparing.
Also why you have used break after return. I think you have to do first break and then return in the end.
One more thing to add. Your for loop should contain braces. Only the first if statement will get executed according to your code.
public int Blanks(int l) { //l = Lane
int x = 0; //The Return
for (int i = 0; i < 6; i++) //The loop
if (l==0){ //Here I keep getting an error saying 'incompatible types'
x = 0;
break;
}
if (l>=1){
x++;
}
if (l>=2){
x++;
}
if (l>=3){
x++;
}
if (l>=4){
x++;
}
return x; //for some odd reason, this is also a void value
}
}
I haven't stepped into your logic. Comment if you face any problem after this.
I don't understand why you are using the for loop here, but this is a way to do it:
public int Blanks(int l) {
int x = 0;
for (int i = 0; i < 6; i++)
if (l==0){
x = 0;
}else {
x++;
}
return x;
}
But in case that l==0 your method will return 5;
If you want to return 0 or 1 then you need to remove the for loop
public int Blanks(int l) {
if (l==0) return 0;
else return 1;
}
And the method with true-false:
public boolean Blanks(int l) {
if (l==0) return false;
else return true;
}
I have a question about this program.
public class Main {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<String>();
for(int i=0; i<100; i++){
arrayList.add("ValueA");
arrayList.add("ValueB");
arrayList.add(null);
arrayList.add("ValueC");
arrayList.add(null);
arrayList.add(null);
}
long startTime = System.nanoTime();
arrayList.removeAll(Collections.singleton(null));
long endTime = System.nanoTime();
System.out.println("ArrayList removal took: " + (endTime - startTime) + "ms");
List<String> linkedList = new LinkedList<String>();
for(int i=0; i<100; i++){
linkedList.add("ValueA");
linkedList.add("ValueB");
linkedList.add(null);
linkedList.add("ValueC");
linkedList.add(null);
linkedList.add(null);
}
startTime = System.nanoTime();
linkedList.removeAll(Collections.singleton(null));
endTime = System.nanoTime();
System.out.println("LinkedList removal took: " + (endTime - startTime) + "ms");
}
}
System output is:
ArrayList removal took: 377953ms
LinkedList removal took: 619807ms
Why is linkedList taking more time than arrayList on removeAll?
As Milkmaid mentioned this is not how you should do benchmarking, but I believe that the results you're getting are still valid.
Let's look "under the hood" and see both implementations:
ArrayList.removeAll calls batchRemove:
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
As you can see, ArrayList first "defragments" the underlying array by overriding the elements that need to be removed with the elements that come afterwards (complement is passed as false so only objects that are not null are copied):
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
The following if (r != size) handles the case that an exception was thrown from c.contains and it uses the "magic function" System.arraycopy to copy the rest of the elements from the current index till the end - this part runs by native code and should be considerably fast, which is why we can ignore it.
And in the last if: if (w != size) {...} it simply assigns nulls to the rest of the list so that objects that are eligible will be able to be collected by the GC.
The total number of operations is O(n) and each operation uses direct access to the array.
Now let's have a look at the implementation of LinkedList which is fairly shorter:
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove(); // <-- calls the iterator remove method
modified = true;
}
}
return modified;
}
As you can see, the implementation uses the iterator in order to remove the elements by calling: it.remove();
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet); // <-- this is what actually runs
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
Which in turn calls:
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index+offset); // <-- here
this.modCount = l.modCount;
size--;
return result;
}
Which calls:
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index)); // <-- here
}
which calls:
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
To sum up
Even though theoretically the remove operation in a LinkedList should be O(1) while ArrayList implementation should take O(n), when dealing with batch-removes ArrayList's implementation is more concise, doing everything in one pass by moving objects to override the ones we remove (kind of defragmentation) while LinkedList' implementation is recursively calling 5 different methods (each of which runs its own safety checks...) for each element it removes, and this ends up with the big overhead that you experienced.
First of all 100 elements are not enough to test performance. But from theory:
Data in array are(usually) stored in memory one after one. In linked list you have value and also the pointer to another object. That's mean when you deleting array you just go through connected piece of memory. O contre If you deleting from Linked list you has to go through the random pieces memory depends on pointer. There are more differences between array and linked list. Like adding element removing element etc. That's why we have array and linked list. Take a look here Array vs Linked list
The answer to this question boils down to the difference in execution times of for loop. When you deep dive into the code of removeAll() of both these objects you see that the removeAll() of ArrayList calls batchRemove() which looks like:
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
On the other hand, when you call the removeAll() of LinkedList, it calls the removeAll() of AbstractCollection which looks like:
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
It is clearly visible that in case of ArrayList, a simple for loop is executed as compared to an Iterator based for loop in LinkedList.
The Iterator is better for data structures like LinkedList but it is still slower that the traditional for loop for arrays.
You can know more about the difference in performance of both of these loops here.
if(handler.obj.isEmpty())
handler.addObject(new Box(x, y, ID.Box));
else{
for(int i = 0; i < handler.obj.size(); i++){
Object tempObj = handler.obj.get(i);
if (tempObj.getX() == x && tempObj.getY() == y && tempObj.getId() == ID.Box)
handler.removeObect(tempObj);
else
handler.addObject(new Box(x, y, ID.Box));
}
}
the handler.addObject() in the else statement seems unreachable or doesn't work
From comment:
public class Handler {
LinkedList<Object> obj = new LinkedList<Object>();
public void tick(){
for (int i = 0; i < obj.size();i++){
Object tempObj = obj.get(i);
tempObj.tick();
}
}
public void render(Graphics g){
for (int i = 0; i < obj.size(); i++){
Object tempObj = obj.get(i);
tempObj.render(g);
}
}
public void addObject(Object obj){
this.obj.add(obj);
}
public void removeObect(Object obj){
this.obj.remove(obj);
}
}
Let's see. Assume first time it runs, x,y is 1,1. So you add Box(1,1).
Next time is run, let's assume x,y is 2,3. So, enter for loop:
i = 0: Not same x,y, so enter else, and add Box(2,3).
i = 1: Same as x,y (yeah, we just added it), so enter if and remove Box(2,3).
Result: Box added and removed again.
Oh yeah, a debugger would have told you the same thing.
Your problem is that your for loop ends in the wrong place. This causes two undesirable symptoms.
Firstly, you're adding your new Box once for every element in your list that doesn't match the box, instead of adding it just once.
Secondly, you're removing some of those new Box objects that you just added, once you get to the end of the loop.
I would recommend rewriting the method like this. Notice how the for loop ends before the new object is added - this makes sure that the object is added at most once. Also notice the return statement after an object is removed - this can be done because once the object is removed, the method has no more work to do.
public void addOrRemoveBox(int x, int y) {
for(int i = 0; i < handler.obj.size(); i++){
Object tempObj = handler.obj.get(i);
if (tempObj.getX() == x && tempObj.getY() == y && tempObj.getId() == ID.Box) {
handler.removeObect(tempObj);
return;
}
}
handler.addObject(new Box(x, y, ID.Box));
}
Lastly, you appear to have written your own class called Object (otherwise this code wouldn't compile). This is probably a bad idea, because it will cause you to get confused between your Object class, and the Object class that's built into Java. I suggest you rename that class.
In the main, whenever I call this method to sort the array, it stops as if it's waiting for a response. Any idea why it's not working?
public void bubbleSort(){
boolean finished = false;
boolean swapOccurred = false;
int i = 0;
int next = i + 1;
while (finished == false)
{
for (; i < theArray.length - 1; i++)
{
if (theArray[i] > theArray[next])
{
swapValues(theArray[i], theArray[next]);
swapOccurred = true;
}
}
if (swapOccurred == false)
{
finished = true;
}
}
}
private void swapValues(int i, int next) {
int temp;
temp = i;
i = next;
next = temp;
}
If it is java, then
The next index is never updated so it stays 1 all the time.
The swap method has no side effect, you want to swap the elements in theArray, but in java methods arguments are passed as values so the next and i variables change the value only inside the swap method, they have nothing to do with the cells of theArray array.
The problem is with your swap.
In C, arguments are passed by value, so when you do the swap, the values being passed in aren't affected, so nothing is happening. You need to pass in pointers to the numbers instead (and then dereference them inside):
private void swapValues(int *i, int *next) {
int temp;
temp = *i;
*i = *next;
*next = temp;
}
And then call it with the address of the variables to swap:
swapValues(&theArray[i], &theArray[next]);
Edit: Ha - #Zielu saw Java, I saw C. Same problem in both cases, and as #Zielu points out, you also need to increment next. I believe you actually just want to use [i+1] as your index in place of next.