This is a follow up question from Problem with array assignment
I now have addcube done like so.. and all works as expected, when I print the array. but when I print the same index's AFTER assignment in another class It tells me their equal to 0. So the values are not 'saving'. Why is this? How would I correct this?
public void addcube(float highx, float lowx, float highz, float lowz){
//Constructing new cube...
System.out.println("f = " + f);
Global.cubes++;
float y = 1.5f;
System.out.println("highx = " + highx + "lowx = " + lowx + "highz = " + highz + "lowz = " + lowz);
//FRONT
Global.camObjCoord[Global.i] = highx;
Global.i++;
System.out.println("cube i = " + Global.i);
}
In both cases I'm printing like so...
int p = 0;
while(p < 72){
System.out.println(Global.camObjCoord[p]);
p++;
}
Global.i = 0 at the beginning.
The only other places the array is being referenced is the following..
cubeBuff = makeFloatBuffer(Global.camObjCoord);
FloatBuffer makeFloatBuffer(float[] arr) {
ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer fb = bb.asFloatBuffer();
fb.put(arr);
fb.position(0);
return fb;
}
There is no further refrences to the array in my code.
Thanks.
I would seriously question your design. You're always refering to that Global class, which apparantly seems to be changed from everywhere, and hence you run into such problems (for instance previously with your NullPointerException).
Try seperate things clearly using encapsulation and do not just use one global state that is operated on by different classes. If classes strictly operate only on their own members then dependencies are reduced and it is much easier to track where data is manipulated.
My guess is that your code looks something like this:
System.out.println(Global.camObjCoord[Global.i]);
addcube(/* values here */);
System.out.println(Global.camObjCoord[Global.i]);
and it's printing out 0. Well, that's not printing out the same index after assignment, because Global.i changes value during addcube. For example, suppose Global.i is 3 before the call to addcube. The call to addcube will set Global.camObjCoord[3] to a value, but then set Global.i to 4, so the final line will print out Global.camObjCoord[4] - i.e. not the value which is just been set.
This sort of thing is precisely why global variables are a bad idea...
Related
Say, for example, I have a double variable in Java:
double alpha = 3;
However, I wanted to create a String variable, including that Double Variable:
String beta = "Alpha has a value of " + alpha;
So that the output would be
//Output
Alpha has the value of 3
However, it will not let me do so, as it says the double value cannot be included in the string value.
As I am doing this for around 150 variables, I want to know how to do it the simplest and shortest way.
Thanks
I am doing this for around 150 variables
A common way of simplifying a repeated task is defining a helper method for it:
String description(String name, Object obj) {
return name + " has a value of " + obj;
}
Now you can use it like this:
String beta = description("Alpha", alpha);
Doing this for 150 variables sounds suspicious - chances are, you have an opportunity to make an array. You can define an array of names, then pair them up with values, like this:
String[] names = new String[] {
"Alpha", "Beta", "Gamma", ...
}
double[] values = new double[] {
1.2, 3.4, 5.6, ...
}
for (int i = 0 ; i != names.length() ; i++) {
System.out.println(description(names[i], values[i]));
}
You can use Double.toString(double).
String beta = "Alpha has a value of " + Double.toString(alpha);
When you need to convert a double to a string, use
Double.toString(double);
Where double is the name of the variable.
So I was trying to perform a simple arithmetic on values within and object 'currentUser' in my one 'pricingAction' class.
The code should add the two volume values(doubles) and set the value of the variable to the sum of the two. In this example the volume_2, and volume_4 variable should be set to the sum of the two.
method 1:
if(filled4 == true){
if(currentUser.getUtility_2().equalsIgnoreCase(currentUser.getUtility_4())){
currentUser.setVolume_2(currentUser.getVolume_2() + currentUser.getVolume_4());
currentUser.setVolume_4(currentUser.getVolume_2() + currentUser.getVolume_4());
}
}
method 2:
if(filled3 == true){
if(currentUser.getUtility_2().equalsIgnoreCase(currentUser.getUtility_3())){
holder = 0;
holder = currentUser.getVolume_2() + currentUser.getVolume_3();
currentUser.setVolume_2(holder);
currentUser.setVolume_3(holder);
}
}
Method 2 returns the value expected and Method 1 appears to be tossing in a duplicate of the value it is setting to.
My question is why does Method 1 do this? I can only assume it is just tacking on the extra sum to the current value but the setter method is a generic this.x = x;
Let's simplify the code a little so it's easier to read:
foo.setX(foo.getX() + foo.getY());
foo.setY(foo.getX() + foo.getY());
Now suppose we start with foo.X = 10, foo.Y = 20.
The first statement will initially compute foo.X + foo.Y - which is 10+20, or 30.
It then sets that (30) as a new value for foo.X.
The second statement will initially compute foo.X + foo.Y, which is now 30+20, or 50. Note that this is using the new value of foo.X. It then sets 50 as a new value for foo.Y.
If you want to set the same value for both properties, you should compute that value once, to avoid the change to the value of the first property from affecting the computation. However, it's clearer to declare the local variable for that value as locally as you can:
double result = foo.getX() + foo.getY();
foo.setX(result);
foo.setY(result);
That's not only correct, but it's also easier to understand and more efficient. Bonus!
Because you have set the value of volume2 before using its new value to set volume4.
currentUser.setVolume_2(currentUser.getVolume_2() + currentUser.getVolume_4());
// volume2 now set with new value
// which you are about to use below
currentUser.setVolume_4(currentUser.getVolume_2() + currentUser.getVolume_4());
Your code is performing two additions (and I suspect you wanted one) -
if(currentUser.getUtility_2().equalsIgnoreCase(currentUser.getUtility_4())){
// Changes volume 2
currentUser.setVolume_2(currentUser.getVolume_2() + currentUser.getVolume_4());
currentUser.setVolume_4(currentUser.getVolume_2() + currentUser.getVolume_4());
}
Should probably be
if(currentUser.getUtility_2().equalsIgnoreCase(currentUser.getUtility_4())){
int newVolume = currentUser.getVolume_2() + currentUser.getVolume_4();
currentUser.setVolume_2(newVolume);
currentUser.setVolume_4(newVolume);
}
I have a quick question in regards to the value of how variable values work. I am working on a program right now, which looks like this:
public void run() {
println("There are " + ATOMS + " initially.");
int atoms = ATOMS;
int year = 0;
while (atoms > 0) {
for (int i = atoms; i > 0; i--) {
println(i);
if( rgen.nextBoolean() ) {
atoms--;
println("The total atoms is " + atoms);
}
println("The total for i is " + i + "\n" );
}
year++;
println("There are " + atoms + " at the end of year " + year );
}
}
At the part with the for loop, and setting the variable i to the value of atoms, is what has me confused. Lets say the value of atoms starts at 20. It goes through the for loop and lets assume that the first time through the RandomGenerator makes it true. So that subtracts 1 from atoms. Then after that the value of i should also be minused due to the i--. So my question is: When I set the variable i to the value of atoms does that just take i and set it to the initial value of 20? And then from there every time I adjust the value of i it is taking off of its own version of 20, and then when I change the value of atoms it, too has its own value. So when I subtract from atoms, that is not also being subtracted from i? That is the only way I can make sense of it because this program is written and works correctly, but that part has me confused.
Thank you very much in advance for any help!
yes you have answered your own question. the variable i and atoms are two separate instances.
when you start the loop you are setting i equal to the same value as atoms but they are still separate variables. therefore inside the loop when you change the value of one it does not affect the other.
Once you set the value of i=atoms, it no longer changes. It is the loop initializer, and will no longer be processed.
"i" of course will be decremented continuously (because of the i-- decrement).
But you can change the value of atoms to whatever and the results will not change.
i=atoms is the initialization in the for loop. So then on, value of i independent of atoms.
for (a = 0; a < filename; a++) {
Map<Double,String> m = new HashMap<Double,String>();
String pre = "abc";
String post = ".txt";
for (int ii = 0; ii < 11; ii++) {
m.put(similarityScore[a],pre + a + post + '\n');
}
SortedSet<Double> set = new TreeSet<Double>(m.keySet());
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
}
Output :
0.5773502691896258 abc0.txt
0.5773502691896258 abc1.txt
0.5773502691896258 abc2.txt
NaN abc3.txt
0.5773502691896258 abc4.txt
NaN abc5.txt
NaN abc6.txt
NaN abc7.txt
NaN abc8.txt
0.5773502691896258 abc9.txt
NaN abc10.txt
This code should be able to sort the double values. But it displays the output on top. What happen ?
The problem is almost certainly NaN.
This is, as the name suggests, not a realy number, and behaves very strangely in terms of comparisons. Is NaN greater than, equal to, or less than 0.5773502691896258? It could be any of those results, and isn't even required to be consistent within a single execution of the program. NaN is not even equal to itself, which says something about how preconceptions of the laws of equality, and strong ordering, go out of the window when NaN is involved.
So the fix is not to use a non-numeric and expect Double.compareTo() to do what you want with it. Depending on what NaN means when returned from similarityScore(), there are several approaches you could take. If it means that it's not a match at all, you could have that method return a Double (rather than a double), return null in these cases, and then only add non-null results to the map. If these results should be displayed anyway, then perhaps you could use a result of 0.0 or -1.0, assuming that's less than any "real" similarity score. If you want something more finessed, then returning something as pure and straightforward as a primitive double is likely going to be the problem, and you may need to return your own (simple) domain class instead.
As an aside - why on earth do you create and populate a HashMap, then use a TreeSet to get the iteration order over the keys? If you simply create m as a TreeMap<Double, String> you get exactly the iteration order you want, so can just iterate overm.entrySet()`. It's clearer, more idiomatic (thus more understandable), and more efficient, so there's no reason not to do this.
for (int ii = 0; ii < 11; ii++) {
m.put(similarityScore[a],pre + a + post + '\n');
}
This puts the same value into the map 11 times - you're not referencing ii inside the loop.
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
This prints the single entry in the map.
You do the above for values 0..filename - Adding a value to the map several times, then printing it and restarting with a new map.
Map<Double,String> m = new HashMap<Double,String>();
for (a = 0; a < filename; a++) {
String pre = "abc";
String post = ".txt";
m.put(similarityScore[a],pre + a + post + '\n');
}
SortedSet<Double> set = new TreeSet<Double>(m.keySet());
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
This creates a map, populates it with values for 0..filename, then prints it sorted. You'll still have issues with NaN which isn't really sortable.
Map<Double,String> m = new TreeMap<Double,String>();
for (a = 0; a < filename; a++) {
String pre = "abc";
String post = ".txt";
m.put(similarityScore[a],pre + a + post + '\n');
}
for (Double d : m.keySet()) {
System.out.println(d + " " + m.get(d));
}
And this uses a TreeMap - No need for the intermediate Set
For any Collection to sort, the type of the value on which you are sorting should be same. And should implement comparable interface.
In your case you have NaN and Double values to sort.
Your loop means you're sorting for each filename separately. You'll need to pull the sorting out of the loop to get those values sorted. (Ooops, #Eric beat me to it.)
How do I multiply 10 to an Integer object and get back the Integer object?
I am looking for the neatest way of doing this.
I would probably do it this way:
Get int from Integer object, multiply it with the other int and create another Integer object with this int value.
Code will be something like ...
integerObj = new Integer(integerObj.intValue() * 10);
But, I saw a code where the author is doing it this way: Get the String from the Integer object, concatenate "0" at the end and then get Integer object back by using Integer.parseInt
The code is something like this:
String s = integerObj + "0";
integerObj = Integer.parseInt(s);
Is there any merit in doing it either way?
And what would be the most efficient/neatest way in general and in this case?
With Java 5's autoboxing, you can simply do:
Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a);
The string approach is amusing, but almost certainly a bad way to do it.
Getting the int value of an Integer, and creating a new one will be very fast, where as parseInt would be fairly expensive to call.
Overall, I'd agree with your original approach (which, as others have pointed out, can be done without so much clutter if you have autoboxing as introduced in Java 5).
The problem with the second way is the way Strings are handled in Java:
"0" is converted into a constant String object at compile time.
Each time this code is called, s is constructed as a new String object, and javac converts that code to String s = new StringBuilder().append(integerObj.toString()).append("0").toString() (StringBuffer for older versions). Even if you use the same integerObj, i.e.,
String s1 = integerObj + "0";
String s2 = integerObj + "0";
(s1 == s2) would be false, while s1.equals(s2) would be true.
Integer.parseInt internally calls new Integer() anyway, because Integer is immutable.
BTW, autoboxing/unboxing is internally the same as the first method.
Keep away from the second approach, best bet would be the autoboxing if you're using java 1.5, anything earlier your first example would be best.
The solution using the String method is not so good for a variety of reasons. Some are aesthetic reasons others are practical.
On a practical front more objects get created by the String version than the more normal form (as you have expressed in your first example).
On an aesthetic note, I think that the second version obscures the intent of the code and that is nearly as important as getting it to produce the result you want.
toolkit's answer above is correct and the best way, but it doesn't give a full explanation of what is happening.
Assuming Java 5 or later:
Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a); // will output 20
What you need to know is that this is the exact same as doing:
Integer a = new Integer(2); // or even just Integer a = 2;
a = a.intValue() * 10;
System.out.println(a.intValue()); // will output 20
By performing the operation (in this case *=) on the object 'a', you are not changing the int value inside the 'a' object, but actually assigning a new object to 'a'.
This is because 'a' gets auto-unboxed in order to perform the multiplication, and then the result of the multiplication gets auto-boxed and assigned to 'a'.
Integer is an immutable object. (All wrapper classes are immutable.)
Take for example this piece of code:
static void test() {
Integer i = new Integer(10);
System.out.println("StartingMemory: " + System.identityHashCode(i));
changeInteger(i);
System.out.println("Step1: " + i);
changeInteger(++i);
System.out.println("Step2: " + i.intValue());
System.out.println("MiddleMemory: " + System.identityHashCode(i));
}
static void changeInteger(Integer i) {
System.out.println("ChangeStartMemory: " + System.identityHashCode(i));
System.out.println("ChangeStartValue: " + i);
i++;
System.out.println("ChangeEnd: " + i);
System.out.println("ChangeEndMemory: " + System.identityHashCode(i));
}
The output will be:
StartingMemory: 1373539035
ChangeStartMemory: 1373539035
ChangeStartValue: 10
ChangeEnd: 11
ChangeEndMemory: 190331520
Step1: 10
ChangeStartMemory: 190331520
ChangeStartValue: 11
ChangeEnd: 12
ChangeEndMemory: 1298706257
Step2: 11
MiddleMemory: 190331520
You can see the memory address for 'i' is changing (your memory addresses will be different).
Now lets do a little test with reflection, add this onto the end of the test() method:
System.out.println("MiddleMemory: " + System.identityHashCode(i));
try {
final Field f = i.getClass().getDeclaredField("value");
f.setAccessible(true);
f.setInt(i, 15);
System.out.println("Step3: " + i.intValue());
System.out.println("EndingMemory: " + System.identityHashCode(i));
} catch (final Exception e) {
e.printStackTrace();
}
The additional output will be:
MiddleMemory: 190331520
Step2: 15
MiddleMemory: 190331520
You can see that the memory address for 'i' did not change, even though we changed its value using reflection.
(DO NOT USE REFLECTION THIS WAY IN REAL LIFE!!)