I have an ArrayList of Minion objects, and when a shield collides with a minion, I want to remove that minion from the ArrayList. However, I can only get it to work in 1 way, but not the other way. can anyone plz explain why?
In all 3 cases, I'm using Android's Renderer's onDrawFrame() method... so I have no control over when it gets called. but here's the code for all 3 ways:
Method 1: (does not work)
public void onDrawFrame(GL10 gl) {
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
the problem is that that last line minions.remove(indexesToRemove.get(i)); doesn't ACTUALLY remove the minions. it DOES get called, with the proper index. i've stepped through the debugger, ran it straight up, and the arraylist isn't modified at all. why is this? actually, in the debugger, that line "minions.remove(indexesToRemove.get(i));" gets called a bijillion times.
Method 2: (still does not work)
public void onDrawFrame(GL10 gl) {
synchronized(minions){
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
}
In here, I thought... "oh maybe since it's not quite synchronized, the drawFrame sometimes gets called too many times and is accessing the arraylist at the wrong time and i need to lock it. but it still doesn't work. again, that line minions.remove(indexesToRemove.get(i)); gets called properly with the right index, but does NOT actually remove the object. i'm watching my shield on the screen slam right into the minion and nothing happens to the minion (it doesn't get removed from the arraylist)
Method #3 (this actually works)
public void onDrawFrame(GL10 gl) {
ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
int len = colliders.size();
for(int i=0; i<len; i++){
GameObject collider = colliders.get(i);
if(OverlapTester.overlapCircleRectangle((Circle)shield1.bounds, (Rectangle)collider.bounds)){
minions.remove(collider); // <---- why does THIS work instead?
}
}
}
this code works perfectly. the shield smacks the minion and the minion drops dead. as you can see here, the ONLY difference is that i'm using the overloaded ArrayList.remove(object) method instead of removing by index. as in the line minions.remove(collider);. why does THIS work ?
can anyone please explain?
on a side note, aside from storing another instance variable copy of the arraylist, is there a better way to manage ArrayList<Minion> colliders = new ArrayList<Minion>(minions); ?
Note: both Shield and Minion are regular Java objects that have a rectangular shape as boundary. all that math checks out just fine. i've tested it in the debugger and the collision detection is accurate. I'm also updating the bounds/positions accurate in the onDrawFrame() method.
Because ArrayList provides two methods that are:
public E remove(int index)
public boolean remove(Object o)
When you invoke minions.remove(indexesToRemove.get(i)), since indexesToRemove is a List<Integer>, the invocation is bound to the second signature in which you remove an element by directly specifying the object, auto-unboxing doesn't turn your Integer into an int so the element is not found and nothing happens.
Try with: minions.remove((int)indexesToRemove.get(i)) so that static binding of the method is correctly applied.
#Jack's answer is correct. For posterity you should be using an Iterator here that you can remove with inside your loop:
// synchronization wrapper here
Iterator<Minion> iterator = minions.iterator();
while (iterator.hasNext()) {
Minion minion = iterator.next();
if( OverlapTester.overlapCircleRectangle(..., minion.bounds)) {
iterator.remove();
}
}
It's treating Integer as an object ref in the 1st two example, cast it to an int
Related
(EDIT: Please note that TwoStacksAsQueue's and ArrayList's add() methods are different, so there are no recursive calls happening. I am still stuck after using the debugger, which is why I am asking for help here.)
I am in the middle of designing a class of two stacks that functions as a queue. When I run it, the last number it prints is 6 as expected. When I uncomment the last three lines of code, however, it prints 3 instead.
The way I see it, it should make no difference if the while loop at the end of the transfer() method is commented out or not. It comes after the print statement, so how could it possibly affect the output? What am I missing here? I have reduced my code to the minimal reproducible example.
public class TwoStacksAsQueue<T> {
final int stackCapacity;
final Stack<T> stack1;
final Stack<T> stack2;
public TwoStacksAsQueue(int stackCapacity) {
this.stackCapacity = stackCapacity;
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void add(T something) {
if (stack1.size() + stack2.size() >= stackCapacity * 2)
throw new RuntimeException("Not enough room in either stack; cannot add");
else if (stack1.isEmpty()) {
stack1.push(something);
} else {
int size = stack1.size();
List<T> popped = new ArrayList<>();
while (!stack1.isEmpty()) popped.add(stack1.pop());
stack1.push(something);
for (int i = size - 1; i >= 0; i--) stack1.push(popped.get(i));
if (stack1.size() > stackCapacity) transfer(stack1, stack2);
}
}
private void transfer(Stack<T> from, Stack<T> to) {
List<T> popped = new ArrayList<>();
System.out.println(from.size());
// while (from.size() > stackCapacity) {
// popped.add(from.pop());
// }
}
}
main method:
TwoStacksAsQueue<Integer> twoStacksAsQueue = new TwoStacksAsQueue<>(3);
twoStacksAsQueue.add(0);
twoStacksAsQueue.add(1);
twoStacksAsQueue.add(2);
twoStacksAsQueue.add(3);
twoStacksAsQueue.add(4);
twoStacksAsQueue.add(5);
The commented out lines of code change the behavior when the stackCapacity is exceeded. In your example, that happens when you push the fourth item. You should focus your debugging efforts there instead of waiting until the sixth item is pushed. If you think that code shouldn't be triggered until you hit twice the stackCapacity, you need to rethink that part.
Your code is hard to follow. In particular, I can't tell why you are creating temporary popped lists instead of using stack2. It seems like you think you are transferring values onto stack2, but you are actually putting them in a temporary popped list that then goes out of scope. You'll have an easier time debugging by printing out all the elements of stack1 and stack2 than trying to discern something based on the size.
Is this usage of elements of an ArrayList:
for(int i=0; i<array_list.size(); i++){
Object obj = array_list.get(i);
//do **lots** of stuff with **obj**
}
faster than this one:
for(int i=0; i<array_list.size(); i++){
//do **lots** of stuff with **array_list.get(i)**;
}
It depends on how many times array_list.get(i) is called in the second code. If it is called only once, there is no difference between both methods.
If it's invoked multiple times, saving the value in a variable may be more efficient (it depends on the compiler and the JIT optimizations).
Sample scenario where the first method may be more efficient, compiled using Oracle JDK's javac compiler, assuming the list contains String objects:
for(int i=0; i<array_list.size(); i++){
String obj = array_list.get(i);
System.out.println(obj);
if(!obj.isEmpty()) {
String o = obj.substring(1);
System.out.println(o + obj);
}
}
In this case, obj is saved as a local variable and loaded whenever it is used.
for(int i=0; i<array_list.size(); i++){
System.out.println(array_list.get(i));
if(!array_list.get(i).isEmpty()) {
String o = array_list.get(i).substring(1);
System.out.println(o + array_list.get(i));
}
}
In this case, multiple invokation for List.get are observed in the bytecode.
The performance difference between getting once and a local variable is almost always neglible. But... if you insist on doing it the hardcore way, this is the fast way to go:
ArrayList<Object> array_list = ...
// cache list.size() in variable!
for (int i=0, e=array_list.size(); i < e; ++i) {
// get object only once into local variable
Object object = array_list.get(i);
// do things with object
}
It caches the lists size into a local variable e, to avoid invoking array_list.size() at each loop iteration, as well as each element in the loop to avoid get(index) calls. Be aware that whatever you actually do with the objects in the loop will most likely be by orders of magnitude more expensive than the loop itself.
Therefore, prefer code readability and simply use the advanced for loop syntax:
ArrayList<Object> array_list = ...
for (Object object : array_list) {
// do things with object
}
No hassles, short and clear. Thats worth far more than a few saved clock cycles in most cases.
Could you tell me, what is the difference between For Loop Java in Code A and B? while both of them gives a same result in executing? and i know what they are doing, but why is For loop written this way in the code *A*
Thanks
The code
//Code A
public class MyArray {
public static void main (String[] args){
int[] a ={1,10,30,40,50};
for (int i : a)
{
System.out.println(i);
}
}
}
//====================================
//Code B
public class MyArray{
public static void main (String[] args){
int[] a ={1,10,30,40,50};
for (int i=0;i< a.length; i++)
{
System.out.println(a[i]);
}
}
}
Iterating over a collection is uglier than it needs to be. Consider the following method, which takes a collection of timer tasks and cancels them:
void cancelAll(Collection<TimerTask> c) {
for (Iterator<TimerTask> i = c.iterator(); i.hasNext(); )
i.next().cancel();
}
The iterator is just clutter. Furthermore, it is an opportunity for error. The iterator variable occurs three times in each loop: that is two chances to get it wrong. The for-each construct gets rid of the clutter and the opportunity for error. Here is how the example looks with the for-each construct:
void cancelAll(Collection<TimerTask> c) {
for (TimerTask t : c)
t.cancel();
}
for each is just a better way of iterating.
Limitation:
in for-each loop you will not be able to know which number of element(index of the element in collection) you are processing, you need to define counter for the same, while in simple for loop i tells you the number of the element you are processing.
Code A by is just syntactic sugar for code B and works on Java versions 5 or later.
The advantage is that you do not have to handle the mundane indexing code on your own.
Code A is also known as the foreach loop
Plus Code A also works if instead of int[] you had a Collection, thus giving you a uniform way of iterating over arrays and collections (or to be ever more precise, any subclass of Iterable)
Practically, no difference, but code A is easier to read and harder to make a mistake.
The shorter version of the for loop means for each index in the array, which quite simply is easier to understand.
The other for loop is a most commonly used which starts from a assigned starting value and goes on till the end of array.
The selection depends on the situation according to me. There might be a time when using the codeA format would give a better understanding to the one who debugging the application.
The answers here have not pointed to a certain vital difference: in code A, you cannot simply change the elements of the array, because the i is just a reference, while in code B, you can do a[i] = //something.
If your array was an array of some Objects and you just wanted to use Mutability, then there is no difference.
Actually both codes are equal as first code if in the right-hand side of the for(:) array rather than an Iterable object (as in this case), the internal code uses an int index counter and checks against array.length. which is equivalent to:
for (int i=0;i< a.length; i++)
{
System.out.println(a[i]);
}
Advantage of first code is its internally handle the end condition and short in writing then the second one.
but if object is iterable then it converts to:
for(Iterator<String> i = iteratableObject.iterator(); i.hasNext(); ) {
String item = i.next();
System.out.println(item);
}
Ok, So I have a method
public static int getTotalLegCountDog (ArrayList<Dog> dogList)
{
int temp = 0;
for (int i = 0; i < dogList.size(); i++)
{
temp = dogList.get(i).getNumLegs();
totalLegsDogs += temp;
}
return totalLegsDogs;
}
It adds up the total legs of dogs and returns them as totalLegsDogs and there is another that totals the legs for cats.
Now I'd like a method that would take both the returned totalLegsDogs and returned totalLegsCats and add them together. My try is below (It returns 0), any help would be great!
public int getTotalLegCount ()
{
totalLegs = totalLegsDogs + totalLegsCats;
return totalLegs;
}
Was not calling the Method correctly. The math in the Problem was solid. The problem was the Method output call.
As far as I can tell, there's nothing wrong with the methods themselves - likely you're calling getTotalLegCount before actually counting the legs.
Fix 1 (preferred): Have getTotalLegCount call the methods.
public int getTotalLegCount (ArrayList<Dog> dogList, ArrayList<Cat> catList) {
totalLegs = getTotalLegCountDog(dogList) + getTotalLegCountCat;
return totalLegs;
}
Fix 2: Make it very clear that the leg-counting methods are to be called first. This is the inferior solution, as it requires more effort on the future programmer's part (and that might be future-you!).
I don't think you've shown us enough of your code to do any troubleshooting. It looks like you must have a global static count for dog legs and cat legs? I can't figure out your use case, but any rate, you need to make sure both your counting methods are called before you do anything with the member variables or else they will not be initialized. Example:
DogCatCounter.getTotalLegDogCount(...);
DogCatCounter.getTotalLegCatCount(...);
new DogCatCounter().getTotalLegCount();
The result from that third line should be correct as long as no other instances of DogCatCounter have modified your static variables. In other words, if you have multiple instances of DogCatCounter, any calls to your counting methods are going to modify your global static members.
Recursion is a new practice for me and I am trying to get better at it and understand how the methods return. I have the following program but am unfailiar with how to use the this keyword. Can you please review the code and walk me through the program showing the values held by the variables as the methods execute?
I have tried numerous things to determine how the value answer in the compute method holds 14 after execution can anyone walk me through the first few recursive calls so I can try and figure out the rest?
public class Recurs1 {
public static void main (String [] arg) {
Recurs1 r = new Recurs1();
r.compute();
}
public void compute() {
int [] stuff = {1, 2, 3, 4};
int answer = this.go(stuff, 0);
System.out.println("The answer is " + answer);
}
private int go(int[] numbers, int spot) {
if (numbers.length == spot) return spot;
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
}
Ok so a few things I notice here:
The purpose of go() seems to be calculating the sum of the numbers in the array. If this is the case, your method should look like this:
private int go(int[] numbers, int spot) {
if (numbers.length - 1 == spot) return numbers[spot];
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
This is because numbers.length in this case will return 4, but the last element in this array is at index 3 (arrays are 0-indexed).
This way, when the function is called with the second parameter set to 3, it will return the value of the last element in the array and then the code will "bubble up" (as I like to call it) and calculate the sum of the elements by subsequently returning the current summed value + the value of the current call.
As for your problem with the this keyword, it's actually very simple. this always refers to the current class instance your code is in. In this case, you create a Recurs1 instance called r in your main function so whenever you call a method on that particular object, the this keyword used in those methods will refer to r. If you created multiple Recurs1 objects (each with potential different internal states) in your program, their respective this references would always point to themselves allowing you to access their member variables and methods.
Hope that helps and good luck, recursion is usually what most people have trouble getting their heads around at first but once you get used to it it's pretty cool!
OK so this is not an answer to your question per se, more like a lesson in recursion.
Keep in mind I have never tried to to do this with a java class.
Recursion means a function that calls itself repeatedly until a answer has been reached, or your function detects you are running out of stack space.
You first step into the function determines if you will call yourself.
When you call yourself you will push a new copy of the data onto the stack and begin executing. I think in the case of java you will allocate a new object into the heap ( don't quote me on this ) and each invocation will have a new set of variables that get populated with new values.
As you recurse deeper and deeper you simply allocate new copies of the object until you find the answer or run out of memory.
If you find the answer you then return the result to the previous level in the stack of objects eg:
int foo(int i ){
if(some condition){
return foo(i);
} else
return i
}
as You can see if the condition tests true the foo() keeps getting called. Now at each call, the variables of foo() are saved for as many levels deep as you go. If the condition tests false then each instance of foo() returns to the previous until you are at the original invocation of foo() which then returns to the caller of foo().
Clear as Mud?