Home > Software engineering >  How to properly add data from String[] to ArrayList<String[]>
How to properly add data from String[] to ArrayList<String[]>

Time:12-11

so for my school project we will be working with an SQL database and have to show the values on a JFrame panel.

For data to show in a JTable we have to require next syntaxt: (def)

JTable table = new JTable(String[][] data , String[] header);

Since I don't know how many queries I will have to handle we will read them into a ArrayList<String[]> . Every time I press the button this method parseJSON will be called and I will create a new 2D-ArrayList consisting of String arrays aka String[] elements

public class DBTest {

    public ArrayList<String[]> dataArr = new ArrayList<>();
    public String[] varArr = new String[3];

    public ArrayList<String[]> parseJSON(String jsonString){
        try {
            JSONArray array = new JSONArray(jsonString);
   
                dataArr = new ArrayList<>();
     
                for (int i = 0; i < array.length(); i  ) {
                    JSONObject curObject = array.getJSONObject(i);
                    varArr[0] = curObject.getString("nameSensor");
                    varArr[1] = curObject.getString("value");
                    varArr[2] = curObject.getString("unitSensor");
                    
                    dataArr.add(varArr);
                    System.out.println(Arrays.toString(varArr));
                }
            for (int i = 0; i < array.length(); i  ) {
                 System.out.println(dataArr.get(i));
            } 
            return dataArr;


        }
        catch (JSONException e){
            e.printStackTrace();
        }
        return null;
    }
}

For the first print: I will get the proper Values e.g.

Output

["Weight","500","g"]

["Height", "3", "m"]

But once I add these String[] arrays to the ArrayList and print it I will get:

Output

["Height", "3", "m"]

["Height", "3", "m"]

CodePudding user response:

Move String[] varArr as a local variable in your method:

public class DBTest {

    public ArrayList<String[]> dataArr = new ArrayList<>();
    //Remove this line of code (delete it)
    //public String[] varArr = new String[3];

    public ArrayList<String[]> parseJSON(String jsonString){
        try {
            JSONArray array = new JSONArray(jsonString);
   
                dataArr = new ArrayList<>();
     
                for (int i = 0; i < array.length(); i  ) {
                    JSONObject curObject = array.getJSONObject(i);
                    //declare it locally
                    String[] varArr = new String[] {
                        curObject.getString("nameSensor"),
                        curObject.getString("value"),
                        curObject.getString("unitSensor")
                    };
                    
                    dataArr.add(varArr);
                    System.out.println(Arrays.toString(varArr));
                }
            for (int i = 0; i < array.length(); i  ) {
                 System.out.println(dataArr.get(i));
            } 
            return dataArr;


        }
        catch (JSONException e){
            e.printStackTrace();
        }
        return null;
    }
}

Other improvements:

  • Try to design your code to work with interfaces rather than concrete classes e.g. return List instead of ArrayList
  • Avoid returning null in case the method failed. It'd be better if you return an empty list or throwing a custom exception with a proper message that helps you understand the issue. This also leverages your maintenance effort.
  • Use attributes only if you need to maintain the state (the values) for later use. Otherwise, it'd be better to use local variables instead. dataArr attribute seems to not be needed (at least from this piece of code).

Wrapping everything, this is how the code would look:

public class DBTest {
    public List<String[]> parseJSON(String jsonString) {
        List<String[]> dataArr = new ArrayList<>();
        try {
            JSONArray array = new JSONArray(jsonString);
            for (int i = 0; i < array.length(); i  ) {
                JSONObject curObject = array.getJSONObject(i);
                String[] varArr = new String[] {
                    curObject.getString("nameSensor"),
                    curObject.getString("value"),
                    curObject.getString("unitSensor")
                };
                    
                dataArr.add(varArr);
                System.out.println(Arrays.toString(varArr));
            }
            for (int i = 0; i < array.length(); i  ) {
                 System.out.println(dataArr.get(i));
            } 
        }
        catch (JSONException e) {
            e.printStackTrace();
        }
        return dataArr;
    }
}

CodePudding user response:

I want to add one point to @LuiggiMendoza's answer....

In Java, arrays are basically Objects. The reason why creating a new array in each iteration (local to the method) is because the original code was literally overwriting the value of a single object and placing said reference to three different index location on the ArrayList rather than creating distinct references. Therefore, the last System.out.print() was printing out the same array element value for each iteration of the list. In fact, even if the array was created outside the loop, the result would've been the same as the original code. EACH ITERATION needs a new array for this to work.

CodePudding user response:

The issue lies in the following block of code.

    public String[] varArr = new String[3];
    ...
    for (int i = 0; i < array.length(); i  ) {
        JSONObject curObject = array.getJSONObject(i);
        varArr[0] = curObject.getString("nameSensor");
        varArr[1] = curObject.getString("value");
        varArr[2] = curObject.getString("unitSensor");
                    
        dataArr.add(varArr);
        System.out.println(Arrays.toString(varArr));
    }

At each iteration of the for-loop, you are doing the following:

  1. Mutate (set values into) the same array instance, which you had instantiated and assigned to the variable varArr before the for-loop.
  2. Add a reference of this array instance to the ArrayList dataArr.

The outcome is that you have added references of the same array instance to the ArrayList multiple times.

Since you were just updating the same underlying array instance over and over again, hence what you get at the second print statement is the last-updated value of that same array instance, printed multiple times.

To fix this, simply move the varArr declaration statement into the for-loop as below. What this does is that at each iteration of the for-loop, a new array instance is created and added to the ArrayList instead.

    for (int i = 0; i < array.length(); i  ) {
        JSONObject curObject = array.getJSONObject(i);

        String[] varArr = new String[3]; // move this here

        varArr[0] = curObject.getString("nameSensor");
        varArr[1] = curObject.getString("value");
        varArr[2] = curObject.getString("unitSensor");
                    
        dataArr.add(varArr);
        System.out.println(Arrays.toString(varArr));
    }
  • Related