Why do I get a "duplicate local variable" error? - java

I have a loop in which I calculate a value and add it it a list. So, I do something like that:
x = getValue()
values.add(x)
while (true) {
x = getValue();
values.add(x)
}
I found out that this approach does not work since I add the same instance to the list. In more details, in every cycle of the loop I re-assign a new value to the x and doing so I change values of all elements that were already added to the list (so in the end I get a list of identical elements).
To solve this problem I did the following:
x = getValue();
Integer[] valueToAdd = new Integer[n];
for (int i=0; i<n; i++) {
valueToAdd[i] = x[i];
}
while (true) {
x = getValue();
y = new Integer[n];
for (int i=0; i<n; i++) {
valueToAdd[i] = x[i];
}
values.add(valueToAdd)
}
In this way I wanted to create a new instance every time want to add a value to the list. But it does not work since I get a duplicate local variable error.
It is also strange to me that I do not have this error if I declare the same variable many times in the loop. The problem appears only if I first declare a new variable outside the loop and then also in the loop.
Is there a way in Java to re-use the same name for different instances?
ADDED
I need to clarify some issues. I did not show all the code. I have the break command in the loop (when a new value cannot be generate, I exit the loop). x and value have Integer[] type.
ADDED 2
Since it was mentioned that the problem can be in the getValue() I need to in more details here. Actually I do not have getValue() in my code (I used getValue() here to make my example shorter). In my code I had:
Integer[] x = new x[n];
while (true) {
for (int i=0; i<n; i++) {
x[i] = y[i];
}
values.add(x)
}
And it did not work since in my values list I had identical elements (and I know that in the loop on every cycle x had a new value).
ADDED 3
Why all elements of my list seems to be the same?

Your problem is not what you think it is. For example take a look at this simple program:
String x = null;
List<String> l = new ArrayList<String>();
for (int i = 0; i < 10; i ++) {
x = String.valueOf(i);
l.add(x);
}
System.out.println(l);
It prints the numbers from 0 to 9. This is because java is pass-by-value (check here). You are not passing the reference to x, you are passing the value of x (in the add method).
So the problem lies in the getValue() method, which returns the same object.
Update: Now the question makes more sense. You are working with the same object x everytime, and just changing its state. In order to put different values just move the declaration inside the loop:
while (true) {
Integer[] x = new x[n];
...
}
If you need it outside the loop, well, simply use another variable there. It does not have to be named x. Since you won't be using it inside the loop anyway.

Related

Add elements with arguments in an array with java

I want to add a new element that has several arguments in an array. I know how to add with just one argument, but with more i don't know.
My code is:
private Calculate[] calculation;
public Element(int numElements) {
calculation = new Calculate[numElements];
}
public void addElement(Date elementDate, double price, ElementType type) {
int numElements = elements.length;
int i = 0;
if (i < numElements) {
Calculate[i] = calculation.elementDate;
Calculate[i] = calculation.price;
Calculate[i] = calculation.type;
i++;
}
}
Calculate[i] = calculation.elementDate;
Calculate[i] = calculation.price;
Calculate[i] = calculation.type;
You shouldn't assign to the same array index 3 times. You're overriding what you've just set.
Try this (Calculate should have a constructor):
Calculate[i] = new Calculate(elementDate, price, type);
You're also maintaining an index i, but you're not looping over anything. i is just incremented from from zero to one and is not really used (apart from an almost useless conditional check).
I suggest you read over a beginners Java tutorial. You seem to be missing a lot of the fundamentals, and Stack Overflow is not a place where we should have to show you how to write a for-loop. It's well-documented and demonstrated in a tonne of tutorials already.
I assume Calculate is a class defined else where with a constructor
There is a couple of issues in this piece of code:
You want to update the array, but specify array. Calculate[] is the array type. The name if the array is calculation. The other thing is that you are trying to access calculation.elementDate etc. but since that is an array, it does not have the field elementDate. I assume your Calculate class has that field. Also, you are not applying a loop. So currently your code will only update the array on index 0.
My code:
public void addElement(Date elementDate, double price, ElementType type) {
for(int i = 0; i < elements.length; i++) { // for loop over all elements in your array
Calculate calculate = new Calculate(elementDate, price, type) // I assume this constructor is available to initialize the Calculate object
calculation[i] = calculate;
}
Hope this helps.

int cannot be converted to int []

new to programming here and i keep getting the error message, incompatible types, int cannot be converted to int [], the question is to add R1 & R2 together if they are of equal lengths and if not, print a message that says 'the arrays must be same length', if that matters, not sure where im going wrong, any help would be greatly appreciated
public int[] arrayAdd(int[] R1, int[] R2)
{
int[] sumArray= new int[R1.length];
if( R1.length!= R2.length)
{
System.out.println("The arrays must be same length");
}
else
{
for(int i=0; i< R1.length; i++)
for (int j=0; j<R2.length; j++)
{
sumArray= R1[i]+ R2[j]; // Error
}
}
return sumArray;
}
not sure where im going wrong
You are attempting to assign an int to a variable whose type is int[].
That is not legal ... and it doesn't make sense.
This:
sumArray= R1[i]+ R2[j];
should be this
sumArray[something_or_other] = R1[i] + R2[j];
... except that you have a bunch of other errors which mean that a simple "point fix" won't be correct.
Hint: you do not need nested loops to add the elements of two arrays.
sumArray[i]= R1[i]+ R2[j]; // updated line
you need to assign to an array element, but you were doing it wrong.
Your code is broken in many several ways, at least:
You declared returning an array but what is the value of it when inputs are of the wrong size? Manage such errors in better ways (stop, throw exception, return error code, etc). At least never display something at this place, this is not the place were you have to tackle the error, this is the place here you detect it, just report it to caller(s).
You (tried to) created space for the returned value but how could this be if conditions for having a return value is not met?
You used Java syntax to declare an array, int []sumArray should be `int sumArray[0].
You can't dynamically allocate an array like this, to capture a dynamic allocation you must use a pointer, an array is not a pointer. But a pointer can be set to the memory address of an allocated array, like int *sumArray = new int[10]
sumArray is an array so to set an element of it use sumArray[index] = ...
So this may be better:
public int *arrayAdd(int[] R1, int[] R2) {
if( R1.length!= R2.length) {
return nullptr;
}
int *sumArray= new int[R1.length];
for(int i=0; i< R1.length; i++) {
sumArray[i] = R1[i]+ R2[i];
}
return sumArray;
}
After question editing
If you want to sum two arrays, element by element, then a single loop is sufficient...
Actually in that line sumArray is an integer array and you are assigning it as integer only and also you haven't declared variable j.
Try this-
public int[] arrayAdd(int[] R1, int[] R2)
{
int[] sumArray= new int[R1.length];
if( R1.length!= R2.length)
{
System.out.println("The arrays must be same length");
}
else
{
for(int i=0; i< R1.length; i++)
{
sumArray[i]= R1[i]+ R2[i]; // Error
}
}
return sumArray;
}

How do you write a counter method to save space and time?

I am working with interface Multiset which is then used by two different classes: ArrayListMultiset and CounterMultiset
The ArrayListMultiset simply uses the .add method to put something in the list. So in a loop like,
Multiset<String> set = new Multiset<String>();
for(int i = 0; i < 10000; i++)
{
set.add("Hello");
}
this will cause the program to add Hello to a list 10,000 times.
Next we have CounterMultiset. It stores a Pair object (another class that takes in (T, Integer), where T is the String, "Hello" and Integer is the number of times it is trying to be added. I have written it like so:
public void add(Multiset<T> item)
{
if(!contains(item))
{
Pair newpair = new Pair(item, 0);
pairs.add(newpair);
}
for(int i = 0; i < pairs.size(); i++)
{
if(pairs.get(i).getFirst() == item)
{
pairs.get(i).changeSecond();
}
}
}
changeSecond() increments the second number in the Object by 1 to show that the word Hello has tried to be added again.
My question is, is this an appropriate way to save space and time for a program? When would it be faster to use a Counter and when would it be faster to simply add "Hello" 10,000 times?
Hello is an intern string in your code.
You will not have a copy of Hello for each element of ArrayListMultiset. You will have a reference to String Pool object.
What is faster for get/put (I assume) - depends on underlying data structures.

Specific NullPointerException Java

i have short question, tell me just why first example don't work and second works.
Code before examples:
Tiles[] myTiles = new Tile[23];
number = 1;
First Example:
for(Tile tile : this.myTiles) {
if (number != this.myTiles.length) {
tile = new Tile(number, getResources().getColor(R.color.puzzle_default));
number++;
}
}
Second Example:
for(Tile tile : this.myTiles) {
if (number != this.myTiles.length){
this.myTiles[number-1] = new Tile(number, getResources().getColor(R.color.puzzle_default));
number++;
}
}
If i use code below in other method in class
this.myTiles[0].getNumber();
It's NullPointerException.
But with Second Example it nicely works.
I really don't know why. Thanks for any response
The first loop makes a copy of each object and is equivalent to
for (int i=0; i < myTiles.length; i++) {
Tile tile;
...
tile = new Tile(...); // set local reference only
}
As elements in an Object array are null by default these would remain unassigned outside the scope of the loop. The original elements of the myTiles remain at their default null values
The for each loop uses an Iterator internally to fetch items from the collection and return you a new reference to a local variable containing each element - overwriting this reference is completely useless, as it is only valid for one for-loop and will be replaced on the next.
"Internally", your first loop would translate to
for (Iterator<Tile> iterator = myTiles.iterator(); iterator.hasNext;){
Tile tile = iterator.next();
tile = new Tile(number, getResources().getColor(R.color.puzzle_default));
number++;
}
In Java, there is no such thing as manipulating a pointer directly. Any time you get a reference to an object, you are getting a copy to a reference, like a pointer to a pointer. For this reason if you do something like:
String s = "hello";
modify(s);
System.out.println(s); // still hello!
void modify(String s){
s = s + " world";
}
You can't actually change the original reference s because the function is manipulating a copy to that reference. In the example above you would need something like this:
String s = "hello";
s = modify(s);
System.out.println(s); // prints 'hello world'
String modify(String s){
return s + " world";
}
The same happens in your for comprehension. The variable tile is bound to the loop and is a copy of a reference in the array. The original reference (the array at the given position) can't be changed directly this way. That's why you need to call directly:
myTiles[i] = // something
Read this article for more information.
So the idiomatic way of modifying an array in java is something like:
for(int i = 0; i < myTiles.length; i++){
myTiles[i] = new Tile(...); // directly reassigning the reference in the array!
}

Get information outside a loop

I've a problem. I want to fill an array with objects containing different Informations.
here is my loop
public FileRecord [] calcPos() throws IOException{
for (int i = 0; i < getEFSFATmaxRecords(); i++){
int blockNumber = i/5;
int recordOffset = i%5;
pos = (recordOffset*100+(getFsatPos() + 512 + 512*blockNumber));
FileRecord rec = new FileRecord(pos,getHeader());
array = new FileRecord[header.getMaxFileRecords()];
array[i] = rec;
System.out.println("FileName: " + array[i].getFileName());
}
return array;
}
It should make different objects of FileRecord. The position depends on the running variable i. t
Then the loop stores everything in the array and returns the array. Ive declared array as a global variable in this calss so I thought the changes inside the loop would directly affect the global array. But it doesnt work. what I'm doing wrong?
Within the array you are doing:
array = new FileRecord[header.getMaxFileRecords()];
This will re-create the array every interation and you'll lose the records stored in it.
You'll need to do this before the loop
You are re initializing your array in every iteration. Below is a correct version of the code you want:
public FileRecord [] calcPos() throws IOException{
FileRecord[] array = new FileRecord[header.getMaxFileRecords()];
for (int i = 0; i < getEFSFATmaxRecords(); i++){
int blockNumber = i/5;
int recordOffset = i%5;
pos = (recordOffset*100+(getFsatPos() + 512 + 512*blockNumber));
FileRecord rec = new FileRecord(pos,getHeader());
array[i] = rec;
System.out.println("FileName: " + array[i].getFileName());
}
return array;
}
As vogel says if the header.getMaxFileRecords() changes within the loop then your array may run out of bound.
Solution: An ArrayList should work.
The problem is that you do:
array = new FileRecord[header.getMaxFileRecords()];
INSIDE the method every time it is invoked (in fact, inside the loop!).
This way, you are "setting" a new FileRecord[] object to the variable (and even worse, this happens many times in your method as the initialization is done in the loop).
Each time this initialization happens, the variable "points to the new FileRecord[] object allocated in memory. The Object that was "pointed to" by array before is not used anymore, and will be destroyed, the when is responsibility of the garbage collector.
(http://javabook.compuware.com/content/memory/how-garbage-collection-works.aspx).
In simple words, you are "recreating" the array again and again inside your loop.
Initialize the object only ONCE before using it in your method (for example in class constructor or in main, before using it in a sense).
Generally, I suggest that you don't use global variables. Search more on class encapsulation, a very important Object-Oriented Programming principle:
(http://www.tutorialspoint.com/java/java_encapsulation.htm).

Categories