简体   繁体   中英

Java Array : Unable to store new values into an array

I am getting battery values from a drone. I am able to display the new battery value on JLabel. However, when I am trying to store these battery values into an int array, it is only store the very first battery value on the array. The subsequent array values will only fill up with the first battery value.

I show an output so you will understand what is happening. The first value is getting from drone while the second value indicate the array index. The output clearly show that the array cannot accept new data for unknown reason.

P/S: I have no idea what is best size of array since I am getting values from drone every seconds. So I have declared an int array with size of 9999999. Any idea how can I set an array to its max size to cater the needs of getting continuous battery values from drone? Those values are being used for drawing graph later.

My code:

public class arDroneFrame extends javax.swing.JFrame implements Runnable, DroneStatusChangeListener, NavDataListener {

      private String text; // string for speech
      private static final long CONNECT_TIMEOUT = 10000;
      public ARDrone drone;
      public NavData data;
      public Timer timer = new Timer();
      public int batteryGraphic=0;
      public int [] arrayBatt = new int[9999999];

      public arDroneFrame(String text) {
          this.text=text;          
      }

      public arDroneFrame() {
         initComponents();             
         initDrone();       
      }

      private void initDrone() {
        try {
          drone = new ARDrone();
          data = new NavData();          
        } catch (UnknownHostException ex) {
        return;     
      } 
        videoDrone.setDrone(drone);        
        drone.addNavDataListener(this);
}

     public void navDataReceived(NavData nd) { 
         getNavData(nd);    
         int battery = nd.getBattery();  
         cmdListOK.jlblBatteryLevelValue.setText(battery + " %"); 
         //JLabel can get updated & always display new battery values 
      }

     public void getNavData(NavData nd){
          for(int i=0;i<arrayBatt.length;i++){
              batteryGraphic= nd.getBattery();
              arrayBatt[i] = batteryGraphic;
              System.err.println("This is stored battery values : " + arrayBatt[i] + "   " + i + "\n");
          }
     }
}

     public static void main(String args[]) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {

              String text = "Welcome!";
              arDroneFrame freeTTS = new arDroneFrame(text);
              freeTTS.speak();

              new arDroneFrame().setVisible(true);
              }
      });
   }

Result:

This is stored battery values : 39   0

This is stored battery values : 39   1

This is stored battery values : 39   2

This is stored battery values : 39   3

This is stored battery values : 39   4

This is stored battery values : 39   5

The problem lies in this method:

public void getNavData(NavData nd){
      for (int batteryValue : arrayBatt){
           arrayBatt[i] = nd.getBattery();
               System.err.println("This is stored battery values : " + arrayBatt[i] + "   " + i + "\n");
      }
   }

You call this method by passing it a NavData instance. This means that whatever value nd contains for nd.getBattery() is being assigned to every index in your array as the loop interates over your battery array.

What you should do, is move the loop outside of the getNavData(NavData nd) method, and pass it a new instance of NavData for each call. When you couple this with the ArrayList suggestion below, you should have a dynamic array of distinct battery values


Side solution

The way that you have declared this array is REALLY SCARY . You should only use the space you need and NOTHING more. I know that you are unsure of what size is actually required, but don't go over-board on it.

You should initialize your array with something smaller;

public int [] arrayBatt = new int[10000];

As a side note: having your class members as public is generally not recommended . You should make them private and create getter/setter methods to retrieve and modify the data, respectively.

Then, have a method that checks to see if your array is full. If it is full, then increase the array size by n/2 , where n is the initial size of your array.

The down-side to this approach is that as your array becomes larger, you are going to spend a lot of time copying the old array to the new array, which is pretty undesirable.

A better solution

Would be to use the built-in ArrayList library, then just append items to your list and let Java do the heavy lifting.

ArrayList<Integer> batteryArray = new ArrayList <Integer>();

you can add items to your list by simply calling:

batteryArray.add(item);

The upside to this solution is that:

  1. The batteryArray size is handled behind-the-scenes
  2. The size of the array is easily retrievable, as well as the elements
  3. ArrayList is a very fast storage structure.

In your loop to print out battery values, you could make it a lot cleaner by implementing a for-each loop.

  • Why are you using System.err to print out dialogs for the battery?? This isn't what System.err is meant to be used for and violates the Principle of Least Astonishment

     public void getNavData(NavData nd){ for (int batteryValue : arrayBatt){ arrayBatt[i] = nd.getBattery(); System.err.println("This is stored battery values : " + arrayBatt[i] + " " + i + "\\n"); } 

    }

I assume that there is some event that is triggered by the drone's hardware. Your loop runs too fast, probably thousands of times per second so there was not time for any battery change and nd.getBattery() returns the same value.

It seems that this is the reason why the values are repeated.

On the other hand, I suspect that navDataReceived is called only when the hardware detects a change and this is why it displays the new value. When getNavData is called you are running a tight loop that locks the execution and prevents your application from receiving this event while the loop is executing.

You should only store a value when you are notified of some change.

I see your implementation of getNavData as fundamentally wrong.

Your 10 million int array is useless in this situation.

I don't know how your application interacts with the drone's hardware but the interface names DroneStatusChangeListener and NavDataListener suggest that you receive some notification when a change occurs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM