Custom Class - have to use new rather than overwriting. Why? - java

I have a custom Vector2 class and a variable named tempVect.
I reuse this throughout a game thread but originally I was just overwriting the new variables
tempVect.x = blahhere;
tempVect.y = blahthere;
tempVect = conversion(tempVect); //this just changes the float to * 0.8
if(ball.velocity != tempVector)
ball.velocity = tempVector;
tempVect.x = thisHere;
tempVect.y = thisThere;
tempVect = conversion(tempVect);
if(ball.position != tempVector)
ball.position = tempVector;
for(int i = 0; i < somevairablenum; i++)
{
tempVect.x = anotherHere;
tempVect.y = anotherThere;
tempVect = conversion(tempVect);
player.position = tempVect;
}
The do somethings would conflict with each other whilst using the tempVect. (so the do something 2 would use the original blahHere and blahThere)
However I solved this by just doing
tempVect = new Vector2(blahHere, blahThere);
//do something
tempVect = new Vector2(thisHere, thisThere);
//do something different
Is anyone able to explain why this was the case? Unfortunately this is my university final project and so any problems I have I need to write down why they happened and how I resolved them, but I don't understand the theory behind this.
Can anyone else?
TIA
----- edit ------
The actual problem was the for loop, the player position was getting mixed up with the ball position.

In the first case, each time you use 'tempVect', it references the same vector, hence the clash.
When you allocate a new vector you create a new object - the .x and .y members are distinct - they refer to a different object (i.e. a different set of variables).
So, even though you are using the 'tempVect' variable each time, 'tempVect' it a reference - and by using 'new' you make it reference different objects, so the assignments do not conflict - since they go to separate objects.

Unfortunately, you've left out the critical part - the content of the "do something"s.
However, most likely one of those "do somethings" was stashing a reference to your vector somewhere, and referring to its contents later. This would then result in it seeing the updated values when it later looks at the contents of the vector.

Related

Re/Create an immutable object that contains an immutable object list

Background
I am trying to create an immutable object that contains a list of immutable objects, as well as object type totals within the list.
I created a slightly sudo gist to try and show what I mean.
Gist - Adjusting an immutable object that contains an immutable object list.
Explanation
My example shows how I'm currently doing it, it does work. However not for all cases.
My VeggieCartView will have a recyclerview that gets filled with a new/saved VeggieCart.
Each VeggieCart has a list of veggies. Veggie totals etc...
I then have a helper class VeggieChanger, it contains an rx.Consumer<Veggie[]> that gets set and accepts any 1:1 veggie changes from the veggie views.
The VeggieCartView sets the consumer so when any one veggie changes, it creates an updated cart using the changes' corresponding cart factory method. The adapter is used to change/retrieve its list.
Working and not
This works well for changing one at a time, however batching changes is throwing concurrency exceptions.
I realize my gist is not runnable and doesn't show most boilerplate, and that I may be fundamentally wrong with some or all of my approaches. With that said I still hope someone can give me advice on how to better implement what I'm trying to do.
If more information is needed to understand, please ask. Thank you for anybody who does have help to offer,
Jon.
I ended up figuring out my main issue.
By adding this to my VeggieCartView:
public void bagAllCanned() {
final Veggie[] canned = new Veggie[cart.canTotal()];
final Veggie[] bagged = new Veggie[canned.length];
int t = 0;
final List<Veggie> veggies = cart.veggies();
for (int i = 0; i < veggies.size(); i++) {
final Veggie veggie = veggies.get(i);
if (veggie.canned()) {
canned[t] = veggie;
if (veggie instanceof Potato)
bagged[t] = Potato.can(veggie);
else if (veggie instanceof Tomato)
bagged[t] = Tomato.can(veggie);
t++;
}
}
for (int i = 0; i < canned.length; i++) {
veggieChange(canned[i], bagged[i]);
}
}
It fixes the concurrency errors.
I'm still unsure if my approach is correct or not. So even though the question is mostly answered, opinions are still VERY welcome.

I can't get to modify my static variable in java

You give a grid (4x4 here). you need to find out the total no of unique paths from (0,0) to (4,4). main() call a function pathify for this. It finds the possible "next steps" and calls it again. When (4,4) is reached noOfPaths++; is supposed to execute. This doesn't happen and I can't find the problem.
import java.util.ArrayList;
public class NoOfPaths {
static int xRows = 4;
static int yColumns = 4;
static int noOfPaths = 0;
/*A robot is located in the upper-left corner of a 4×4 grid.
* The robot can move either up, down, left, or right,
* but cannot go to the same location twice.
* The robot is trying to reach the lower-right corner of the grid.
* Your task is to find out the number of unique ways to reach the destination.
**/
static ArrayList validNeighbours (int x,int y, ArrayList visited) {
ArrayList valid = new ArrayList();
if((x+1 <= xRows) && !visited.contains(((x+1)*10)+y) ) {
valid.add(((x+1)*10)+y);
}
if((x-1 >= 0) && !visited.contains(((x-1)*10)+y) ) {
valid.add(((x-1)*10)+y);
}
if((y+1 <= yColumns) && !visited.contains(x*10+y+1) ) {
valid.add(x*10+y+1);
}
if((y-1 >= 0) && !visited.contains(x*10+y-1) ) {
valid.add(x*10+y-1);
}
return valid;
}
static void pathify(int x,int y, ArrayList alreadyVisited) {
if(x == xRows && y == yColumns) {
noOfPaths++;
} else {
alreadyVisited.add(x*10+y);
ArrayList callAgain = new ArrayList();
callAgain = validNeighbours(x,y,alreadyVisited);
for (int t=0,temp; t<callAgain.size(); t++) {
temp=(int) callAgain.get(t);
pathify(temp/10, temp%10, alreadyVisited);
}
}
}
public static void main(String[] args) {
ArrayList alreadyVisited = new ArrayList();
pathify(0, 0, alreadyVisited);
System.out.println(noOfPaths);
}
}
The error is in how you're handling alreadyVisited. The first time pathify is called, this list will contain only the initial square (0,0), which is fine. Here's the important part of your code:
for (int t=0,temp; t<callAgain.size(); t++) {
temp=(int) callAgain.get(t);
pathify(temp/10, temp%10, alreadyVisited);
}
You've found the neighbors of the initial cell. Your code will pick the first neighbor; then it will find paths starting with that neighbor, and the recursive calls to pathify will add cells to alreadyVisited.
Now, after all the recursive calls come back, you're ready to find cells starting with the second neighbor of the initial cell. But you have a problem: alreadyVisited still has all the cells it's collected from the paths it found starting with the second neighbor. So you won't find all possible paths starting with the second neighbor; you won't find any path that includes any cell in any path you've previously found. This isn't what you want, since you only want to avoid visiting the same cell in each path--you don't want to avoid visiting the same cell in all your previous paths. (I simplified this a little bit. In reality, the problem will start occurring deeper down the recursive stack, and you won't even find all the paths beginning with the first neighbor.)
When implementing a recursive algorithm, I've found that it's generally a bad idea to keep an intermediate data structure that is shared by recursive invocations that will be modified by those invocations. In this case, that's the list alreadyVisited. The problem is that when an invocation deeper down the stack modifies the structure, this affects invocations further up, because they will see the modifications after the deeper invocations return, which is basically data they need changing underneath them. (I'm not talking about a collection that is used to hold a list of results, if the list is basically write-only.) The way to avoid it here is that instead of adding to alreadyVisited, you could create a clone of this list and then add to it. That way, a deeper invocation can be sure that it's not impacting the shallower invocations by changing their data. That is, instead of
alreadyVisited.add(x*10+y);
write
alreadyVisited = [make a copy of alreadyVisited];
alreadyVisited.add(x*10+y);
The add will modify a new list, not the list that other invocations are using. (Personally, I'd declare a new variable such as newAlreadyVisited, since I don't really like modifying parameters, for readability reasons.)
This may seem inefficient. It will definitely use more memory (although the memory should be garbage-collectible pretty quickly). But trying to share a data structure between recursive invocations is very, very difficult to do correctly. It can be done if you're very careful about cleaning up the changes and restoring the structure to what it was when the method began. That might be necessary if the structure is something like a large tree, making it unfeasible to copy for every invocation. But it can take a lot of skill to make things work.
EDIT: I tested it and it appears to work: 12 if xRows=yColumns=2, 8512 if both are 4 (is that correct?). Another approach: instead of copying the list, I tried
alreadyVisited.remove((Object)(x*10+y));
at the end of the method ((Object) is needed so that Java doesn't think you're removing at an index) and that gave me the same results. If you do that, you'll make sure that alreadyVisited is the same when pathify returns as it was when it started. But I want to emphasize that I don't recommend this "cleanup" approach unless you really know what you're doing.

Assigning New Object to a Generic Array Index

I'm POSITIVE that my title for this topic is not appropriate. Let me explain. The purpose of this is to duplicate a "Profile" application, where I have a profile and so would you. We both have our own followers and in this example, we both follow each other. What this method is needed to return is a cross reference based on whom you follow that I do not. I need this method to return to me a recommended Profile object that I do not already have in my array. Right now I'm having a difficult time with one line of code within a particular method.
One of my classes is a Set class that implements a SetInterface (provided by my professor) and also my Profile class that implements a ProfileInterface which was also provided. In my code for the Profile class, I have the following object: private Set<ProfileInterface> followBag = new Set<ProfileInterface>(); which utilizes the Array bag methods from my Set class with the ProfileInterface methods I've made.
Here is the method (not complete but can't move further without my problem being explained):
public ProfileInterface recommend(){
Set<ProfileInterface> recommended;
ProfileInterface thisProfile = new Profile();
for(int index = 0; index < followBag.getCurrentSize(); index++){
Set<ProfileInterface> follows = followBag[index].toArray();
for(int followedFollowers = 0; followedFollowers < follows.getCurrentSize(); followedFollowers++) {
if()
//if Profile's do not match, set recommended == the Profile
}
}
return recommended;
}
The purpose of this method is to parse through an array (Profile as this example) and then take each of those sub-Profiles and do a similar action. The reason for this much like "Twitter", "Facebook", or "LinkedIn"; where each Profile has followers. This method is meant to look through the highest Profiles follows and see if those subProfiles have any followers that aren't being followed by the highest one. This method is then meant to return that Profile as a recommended one to be followed. This is my first dealing with Array Bag data structures, as well as with generics. Through "IntelliJ", I'm receiving errors with the line Set<ProfileInterface> follows = followBag[index].toArray();. Let me explain the reason for this line. What I'm trying to do is take "my" profile (in this example), and see who I'm following. For each followed profile (or followBag[index]) I wish to see if followBag[index][index] == followBag[index] and continue to parse the array to see if it matches. But, due to my confusion with generics and array bag data structures, I'm having major difficulties figuring this out.
I'd like to do the following:
//for all of my followers
//look at a particular followed profile
//look at all of that profile's followers
//if they match one of my followers, do nothing
//else
//if they don't match, recommend that profile
//return that profile or null
My problem is that I do not know how to appropriately create an object of a Profile type that will allow me to return this object
(in my method above, the line Set<ProfileInterface> follows = followBag[index].toArray();)
I'm trying to make an index of my Profile set to an object that can later be compared where my difficulties are. I'd really appreciate any insight into how this should be done.
Much appreciated for all help and Cheers!
When you do:
Set<ProfileInterface> follows = followBag[index].toArray();
you're trying to use Set as Array. But you can't.
Java will not allow, because Set and Array are different classes, and Set does not support [] syntax.
That is why you get error. For usefollowBag as Array you have to convert it:
ProfileInterface[] profileArray = followBag.toArray(new ProfileInterface[followBag.size()]);
for(int i=0; i<profileArray.length; i++){
ProfileInterface profile = profileArray[i];
//do what you would like to do with array item
}
I believe, in your case, you don't need assign Set object to generic Array at all. Because you can enumerate Set as is.
public class Profile {
private Set<ProfileInterface> followBag = new HashSet<Profile>();
...
public Set<ProfileInterface> recommended(){
Set<ProfileInterface> recommendSet = new HashSet<ProfileInterface>();
for(Profile follower : followBag){
for(Profile subfollower : follower.followBag){
if(!this.followBag.contains(subfollower)){
recommendSet.add(subfollower);
}
}
}
return recommendSet;
}
}
I also added possibility of returning list of recommended profiles, because there is may be several.

Java - Error in eclipse: the left hand side of an assignment must be a variable

This is a small part of my code. My project is to simulate a whole school system. To add teachers, courses etc. All of my class members are private, so i created setters and getters methods. I try to give to 'teachersNum' a value and this must be automatic(not from keyboard). So i want to give it value 1 if its the first teacher etc. I hope you can understand. Sorry for my English.
public void addTeachersList(Teachers teachers) {
if(this.teachersSize<100){
this.teachersList[this.teachersSize] = teachers;
this.teachersList[this.teachersSize].getTeacherNum() = this.teachersSize -1;
this.teachersSize++;
}
}
You'll have to call a setter:
this.teachersList[this.teachersSize].setTeacherNum(this.teachersSize-1);
Calling the getter getTeacherNum just gives you the number, it isn't a reference to that property.
Although I must say, you'd really do yourself a favor by using a List implementation instead of arrays.
In this line
this.teachersList[this.teachersSize].getTeacherNum() = this.teachersSize -1;
getTeacherNum() returns a value. You can't assign to it.
You have the problem here
this.teachersList[this.teachersSize].getTeacherNum() = this.teachersSize -1;
.getTeacherNum() will return a value which must be stored in a variable on left side.
eg:
temp = .getTeacherNum();
And its better to use a static variable to keep the count of teachers, so every time a teacher is created he/she gets a nos which is different from the previous one
eg:
xxxx001
xxxx002
xxxx003
You have the problem here
this.teachersList[this.teachersSize].getTeacherNum() = this.teachersSize -1;
.getTeacherNum() will return a value which must be stored in a variable on left side.
eg: temp = .getTeacherNum();
And its better to use a static variable to keep the count of teachers, so every time a teacher is created he/she gets a nos which is different from the previous one
eg:
xxxx001
xxxx002
xxxx003

Get the array from an AtomicLongArray

Using Java 1.6 and the AtomicLongArray, I'd like to "copy" the original AtomicLongArray into a new one. There is a constructor that takes an array (AtomicLongArray(long[])), so I thought I could just get the array from the original one and give it to the constructor.
Sadly, the actual long[] in the AtomicLongArray is private and there seem to be no getters for it. Is there any way to do this, meaning copy the values from one AtomicLongArray to another? I can't create my own class based on this class, as the sun.misc.Unsafe class is not available to me.
This is needed because I'm going to iterate over the values, and I don't want them modified by another thread during iteration. So I thought I could make a copy and use that for the iteration...
Thanks!
Phillip
I suspect you have to create your own long[] and populate it first, or just iterate over the original:
AtomicLongArray copy = new AtomicLongArray(original.length());
for (int i = 0; i < copy.length(); i++)
{
copy.set(i, original.get(i));
}
Note that although each individual operation in AtomicLongArray is atomic, there are no bulk operations - so there's no way of getting a "snapshot" of the whole array at time T. If you want that sort of behaviour, I believe you'll need to use synchronization.
This data structure allows concurrent updates to individual entries in the collection. There is not overall lock, so you can't prevent another thread changing the contents while you are iterating over it.
If you need this, you need a workaround, e.g. copy the array and loop again to check it hasn't changed. If changed, repeat. Or you need a collection which supports a global lock.
long[] copy = new long[original.length()];
boolean changed = true;
// repeat until we get an unchanged copy.
while(true) {
for (int i = 0; i < copy.length(); i++) {
long l = original.get(i);
changed |= copy[i] != l;
copy[i] = l;
}
if (!changed) break;
changed = false;
}
This is not completely safe, but may be enough for what you need.

Categories