Elements in java ArrayList taking up two places - java

I have made a LinkedList to store State objects which is a class I have created. I can add states to the list as expected, but whenever I try the size() method on the list it always returns twice the amount of elements I have added. Why is it doing this and how can I then use the get(n) method if each element has 2 values of n?
Here's the code used to create and add to the list:
static ArrayList<State> stateTable = new ArrayList<State>();
stateTable.add(new State(new Item(0,0)));
I will add that the adding to the list is done inside the constructor for State objects so that all created States get put in the stateTable.
Thanks

I will add that the adding to the list is done inside the constructor
for State objects so that all created States get put in the
stateTable.
If you already add the states to your list inside the constructor and additionally have the line
stateTable.add(
new State(new Item(0,0)) // <= first time inside new State(...)
); // <= second time explicitely in this line
then you are indeed adding it twice.

search for .add( and make sure you are not calling it in multiple places.
If your ArrayList is not marked as private mark it as private.
If you return your ArrayList from a method do return a read-only version via: Collection.unmodifiableList(stateTable);
If you load the data in one method or the constructor and do not intend to do it anywhere else than do it something like:
private static final List<State> stateTable;
static
{
final List<State> temp;
temp = new ArrayList<State>();
temp.add(new State(new Item(0,0)));
stateTable = Collections.unmodifiableList(stateTable);
}
Using the unmodifiableList will cause your program to crash if you add objects into it.

Related

Arrays.asList add ArrayList rather than specific members

I have an object which contains some package-private member variables and I'm adding them to a Google Sheets v4 ValueRange in another object. The current code looks a little bit like this:
List<List<Object>> data = new ArrayList<>();
...
/**
* Sets all the values in the ValueRange member variable
* #return the ValueRange object
*/
ValueRange requestBuilder() {
...
//For each case, add it to the value range
for (int i = 0; i < closedCases.size(); i++) {
data.add(
Arrays.asList(
closedCases.get(i).number,
closedCases.get(i).priority,
closedCases.get(i).firstResp,
closedCases.get(i).accName,
closedCases.get(i).subject,
closedCases.get(i).assigned,
closedCases.get(i).lastUpdated,
closedCases.get(i).daysOld,
closedCases.get(i).jiraCase
)
);
}
vr.setValues(data);
return vr;
}
The question that I'm seeking to answer is, is there any way to do Arrays.asList( closeCases.get(i) ) or add some kind of method on the case object to simply fill all that stuff in, rather than calling out each member variable in the Arrays.asList(). I'm also aware I can use a foreach, but would still need to use the same notation for adding items, which is what I'm trying to avoid.
In case anyone is interested, closedCases is just an ArrayList of an object with some strings and doubles in it.
You somehow need to specify what fields go into this list, in what order. If you want to capture all fields, you could use reflection to iterate over the object (potentially choosing declared, not inherited fields, and potentially choosing only package-private fields), as described here.
But that is not the idiomatic way to do it in Java.
Can you change the definition of the "object which contains some package-private member variables" so that instead it has a Map with key-value pairs?
You could add a List field in the object that is held by closedcases and call that field from inside the loop.
For instance, say the object is Foo,
Inside foo, create a field:
ArrayList<String> allFields = new ArrayList<String>{number. priority …… };
Method:
public ArrayList<String> getAll() {
return allFields;
}
And from inside the loop, just do
data.add(closedCases.get(i).getAll());
If the fields are not just string, you could create different arraylist that holds different types of object, which will increase the list again but could be substantially less that what you gave us.

Why do "ArrayList.remove" remove both in local variable and in myApplicationClass? [duplicate]

This question already has answers here:
Why does one arraylist change when a copy of it is modified
(6 answers)
Closed 5 years ago.
I have a MyApplicationClass into which I stock An ArrayList, then I create a variable ArrayList in my MainActivity and assign it the variable in MyApplciationClass and finally I call remove to the local variable to remove a value but the value is removed from both MyApplicationClass and the localvariable and it can be possible because I just retrieve the list from MyApplicationClass I didin't make anything else ?
Here is my code:
MyApplicationClass:
private ArrayList<String> text = new ArrayList<>();
public ArrayList<String> getText() {
return text;
}
public void addTest(String input) {
text.add(input);
}
MainActivity:
//When click on a button:
final MyApplicationClass myApplicationClass = (MyApplicationClass) getApplicationContext();
//I add some example values
myApplicationClass.addTest("1");
myApplicationClass.addTest("2");
//Here I retrieve the variable in MyApplicationClass to put in into a local variable:
ArrayList<String> testlocal = myApplicationClass.getText();
//And here I remove a value from the localvariable testlocal:
test.remove(1);
But when I debug and see variable I can see that the value is correctly deleted in testlocal but too in text in MyApplicationClass but I just want to remove a value from textlocal.
Thanks a lot.
The two variables refers to the same ArrayList object.
This assignment makes testlocal refers to the ArrayList object of the MyApplicationClass instance :
ArrayList<String> testlocal = myApplicationClass.getText();
To create a new ArrayList, you have to create a new object by using the new operator :
ArrayList<String> testlocal = new ArrayList<>(myApplicationClass.getText());
Now removing (or even adding) one element in any of these two ArrayList objects will never be reflected in the other ArrayList object.
But note that new ArrayList(Collection c) will not make a deep copy of the elements copied.
So modifying the state of any element in one or the other ArrayList object will be still reflected in the other.
In your actual case, it is not a problem as the Lists store only String values that are de facto immutable.
You need to create a copy of the original list. Also, generally it's better to depend on the List interface instead of the ArrayList class.
You can create the copy in the getText() method. This is easy because you need to modify the code on only one place. On the other hand, no outer class will be able to change your MyApplicationClass:
public List<String> getText() {
return new ArrayList<>(text);
}
Alternatively, you can create a local copy whenever you retrieve it:
List<String> testlocal = new ArrayList<>(myApplicationClass.getText());

How to append items to ArrayList?

I've got a function to create syllables for words.
I use it like this: syllables(word1field); - creates List with syllables: aa,bb,cc
and syllables(word2field); - creates List with syllables: dd,ee,ff
And in the result I get dd,ee,ff, but I need aa,bb,cc,dd,ee,ff.
Is there possibility to append second list to first?
You get dd,ee,ff because when you call the same method again, it overrides the first ArrayList that is created.
The best thing you could do, that I can think of, is to make your ArrayList global because currently you just keep getting rid of the previous values and create a new ArrayList with the new values you give it. Try doing something like:
public class MyClass {
private List<String> myArray;
public MyClass() {
myArray = new ArrayList<String>();
}
public void syllables(wordfield) {
// do whatever you need to with wordfield
myArray.add(syllable);
}
I don't know how you've got everything laid out but this is the best solution I can think of.

Pointer with public array

Here is the thing- my Main method only calls InitGui. Inside the whole class (basically the whole file, i have the InitGui method and a few public static gui objects. One of the objects is actuall an array
public static JButton Keys[] = null;
And I have a method called placeKeys that gets the location for each JButton "Keys" and places it on the panel. The whole code works when I do not use this method, basically instead of for i=0 to whatever, I want just call placeKey(arguments here...) instead of
for each jButton to be placed like this
for i=0 to whatever
Keys[i] = new JButton(jBStringArray[i]);
Keys[i].setLocation(2 + i*kSize,2+row*50);
Keys[i].setSize(50, kSize);
keyboardPane.add(Keys[i]);
I have the method written down but it reports a pointer error at the placeKeys when it tries to access the Keys[] , meaning the first line of the method
Hope you understood me
Before your for loop (either when you declare it, or, if you rely on the null check, just before the for loop) you need to create the array with Keys = new JButton[whatever+1];. Oh and please start your variable names with a lowercase letter - it's the universally-accepted thing to do.
//assuming jBStringArray is already defined here
public static JButton Keys[] = new JButton[jBStringArray.length];

ArrayList<String> Object assignment

I have two separate objects ArrayList<String> in two separate packages Top and top10. I assign the value of top10 to Top in my activity. And now if I remove an element from Top it also gets removed from top10. I don't know why is this happening? I feel totally dumbfounded. Is there something I don't know about java? Or is it android?
This is my activity code:
ArrayList<String> Top = new ArrayList<String>();
// ServiceCall is the name of the class where top10 is initialized.
Top = ServiceCall.top10;
System.out.println("top WR: "+ServiceCall.top10);
if(Top.get(0).equals("Please Select")) Top.remove(0);
System.out.println("top WR: "+ServiceCall.top10);
The second printed out statement has one element less than the one before.
You are pointing to the same Object.
Top = ServiceCall.top10;
is not creating a new Object, but making a reference to the other one, hence all changes in both pointers will be reflected in the same Object.
You'll have to create a new one passing the other one as parameter:
List<String> Top = new ArrayList<String>(ServiceCall.top10);
You are pointing Top to top10, not creating a new list (your initializer is effectively unused right now, as you are just repointing it to the other list.)
You should do:
ArrayList<String> Top = new ArrayList<String>(ServiceCall.top10);
This will create a shallow copy.

Categories