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:
The batteryArray size is handled behind-the-scenes
The size of the array is easily retrievable, as well as the elements
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.
Related
I have a method that return a number:
public String getNum()
{
Random random = new Random();
return random.nextInt(1000) + "";
}
And I have this method that stores an object
public void store(User user)
{
String str = getNum();
user.setIdCode(str);
for (User users: userList)
{
if(users.getId() == user.getId())
{
user.setIdCode(getNum);
}
}
}
if Id is excited than re-set the id. This is for sure checks if the id exists the first time but how about the second time that id is set. there would be a possibility of repeating the same number. At the same time we cant go in infinite loop.
What you can try is add a few random numbers in a Set and then use them separately whenever you want.
What I mean by it is that if you're trying to get a random number every time, you can just store some random numbers at once and then retrieve them one by one when you need them.
In code, put this in some method called storeRandomNumbers() and call it in the beginning of your program. Also, declare the Set as a global variable.
You can also make a separate variable to keep track of how many random numbers have been used up and use it to retrieve the next random number from the Set.
The code would look something like this (makes changes according to your needs):
Random rand = new Random();
Set<Integer> uniqueRandoms = new HashSet<>();
while (uniqueRandoms.size()<10){
uniqueRandoms.add(rand.nextInt(11));
}
for (Integer i : uniqueRandoms){
// System.out.print(i+" ");
// retrieve them from here and use them whenever you want
}
Edit:
Yes as #Andreas gave the link to suggest, you don't compare Strings with ==, rather you use the equals() method.
So, the question is. If I'm calling method guess from class - Player and it is a void-type method without return statement in it, how come I'm able to store result of number = (int)(Math.random() * 10) in number variable for 3 different objects (p1, p2, p3)?
I'm little confused about when should I use return statement or void-type methods, because if number = (int)(Math.random() * 10) is giving some results which I want to use, why then I don't need to return this results from a method to pass them to the number variable which I declared in int number = 0;
public class Player {
int number = 0;
public void guess() {
number = (int)(Math.random() * 10);
System.out.println("I'm guessing " + number);
}
}
A void method does not return anything, but it still allows you to do things. (Print to the console, modify variables etc) The void keyword just means that it doesn't return a value. (In void methods you can still use a blank return; to end the method) And because you are modifying your number variable in the GuessGame object the changes you make will stay even though you don't return a variable. Try this simple test to see what I mean:
//In your GuessGame class
int number = 0;
public void foo() {
number++;
}
public static void main(String[] args) {
GuessGames games = new GuessGames();
games.foo();
System.out.println(games.number);
//Outputs 1
}
docs for the return statement
The point is: where is the result of Math.random() * 10 physically stored on your computer when your program is run? You list two options.
Options 1: Instance field
In this case the compiler instructs your operating system to reserve space for a int variable for the whole life of the Player object. The player object may live for microseconds, seconds, minutes, hours, days, months, ... it depends! This storage space is usually find in the RAM of the computer and from Java you can access it with the syntax myPlayer.number as long as you have a Player reference somewhere.
Options 2: Return value
In this case the compiler finds the space to store the result of the computation in a register of the Java virtual machine, that you can mentally map to a register of the physical processor. This value will only at best survive for a couple of processor cycles (there are gazillinos in a GHz CPU, so it's really a tiny little fracion of a second) if you don't store it somewhere else - and if you don't it's lost forever. See the following example:
private int someRandom;
private int gimmeARandom() {
return Math.random() * 10;
}
private int test() {
int someRandom = gimmeARandom(); // --> store the value until end of method
this.someRandom = someRandom; // --> further keep it so we can read it later
gimmeARandom(); // --> what did it returned? We'll never know
}
Void is different than static - void just means the function does not return anything, but it can still be a instance method, i.e. one that is associated with each new instance of a class. I think you're confusing this with the functionality of static, which allows methods to be called without an instance of the class.
Is there a way to concatenate two Strings (not final) without allocating memory?
For example, I have these two Strings:
final String SCORE_TEXT = "SCORE: ";
String score = "1000"; //or int score = 1000;
When I concatenate these two strings, a new String object is created.
font.drawMultiLine(batch, SCORE_TEXT + score, 50f, 670f);//this creates new string each time
Since this is done in the main game loop (executed ~60 times in one second), there are a lot of allocations.
Can I somehow do this without allocation?
The obvious solution is to not recreate the output String on every frame, but only when it changes.
One way to do this is to store it somewhere outside your main loop and update it when a certain event happens, i.e. the "score" actually changes. In your main loop you then just use that pre-created String.
If you can't/or don't want to have this event based approach, you can always store the "previous" score and only concatenate a new String when the previous score is different from the current score.
Depending on how often your score actually changes, this should cut out most reallocations. Unless of course the score changes at 60 fps, in which case this whole point is completely mute because nobody would be able to read the text you're printing.
Seems that drawMultiLine accepts not a String, but CharSequence. Thus you may probably implement your own CharSequence which does not actually concatenates two strings. Here's the draft implementation:
public class ConcatenatedString implements CharSequence {
final String left, right;
final int leftLength;
public ConcatenatedString(String left, String right) {
this.left = left;
this.right = right;
this.leftLength = left.length();
}
#Override
public int length() {
return leftLength+right.length();
}
#Override
public char charAt(int index) {
return index < leftLength ? left.charAt(index) : right.charAt(index-leftLength);
}
#Override
public CharSequence subSequence(int start, int end) {
if(end <= leftLength)
return left.substring(start, end);
if(start >= leftLength)
return right.substring(start-leftLength, end-leftLength);
return toString().substring(start, end);
}
#Override
public String toString() {
return left.concat(right);
}
}
Use it like this:
font.drawMultiLine(batch, new ConcatenatedString(SCORE_TEXT, score), 50f, 670f);
Internally in your case drawMultiline just needs the length and charAt methods. Using ConcatenatedString you create only one new object. In contrast when you use SCORE_TEXT + score, you create a temporary StringBuilder which creates internally char[] array, copies the input symbols, resizes the array if necessary, then creates the final String object which creates the new char[] array and copies the symbols again. Thus it's likely that ConcatenatedString will be faster.
Didn't understand the question the first time around. Have you tried using the following?
SCORE_TEXT.concat(score);
I dont think you can populate a value without allocation a memory for it.. what best you can do is create a global string variable and provide the value of SCORE_TEXT + score to it. Use that global string variable in font.drawMultiLine() method.
This way you can minimize the amount of memeory allocated as memory is allocated only once and the same location is updated again & again.
String is designed to be immutable in Java. use StringBuilder
I am developing desktop app in Java 7. I have here a situation. At the method below
private synchronized void decryptMessage
(CopyOnWriteArrayList<Integer> possibleKeys, ArrayList<Integer> cipherDigits)
{
// apply opposite shift algorithm:
ArrayList<Integer> textDigits = shiftCipher(possibleKeys, cipherDigits);
// count CHI squared statistics:
double chi = countCHIstatistics(textDigits);
if(chi < edgeCHI) // if the value of IOC is greater or equal than that
{
System.err.println(chi + " " + possibleKeys + " +");
key = possibleKeys; // store most suitable key
edgeCHI = chi;
}
}
I count the value called 'chi' and based on that if 'chi' is less than 'edgeCHI' value I save the key at instance variable. That method is invoked by some threads, so I enforce synchronization.
When all the threads complete the program continues to execute by passing control to a method which controls the sequence of operations. Then this line has been executed at that method:
System.err.println(edgeCHI+" "+key+" -");
It prints correct value of 'chi', as has been printed the last value of 'chi' at decryptMessage method, but the value of key is different. The 'decryptMessage' method has been invoked by threads which generate key values.
I store the key value as global variable
private volatile CopyOnWriteArrayList<Integer> key = null; // stores the most suitable key for decryption.
Why do I have two different key values? The values itself are not important. The matter is that the value of key printed at the last call at 'decryptMessage' method (when chi < edgeCHI) must match the one printed at the method which controls the flow of operations.
This is how you create threads:
for(int y = 0; y < mostOccuringL.length; y++){// iterate through the five most frequent letters
for(int i = (y + 1); i < mostOccuringL.length; i++ ){//perform letter combinations
int [] combinations = new int[2];
combinations[0] = y;
combinations [1] = i;
new KeyMembers(""+y+":"+i ,combinations, keywords, intKeyIndex, cipherDigits).t.join();
}
}
Within run method you invoke decryptMesssage method in order to identify most feasible decryption key.
I have been trying to figure out what is the prob for two days, but I don't get it.
Suggestions?
Relying on syserr (or sysout) printing to determine an order of execution is dangerous - especially in multi-threaded environments. There is absolutely no guarantuee when the printing actually occurs or if the printed messages are in order. Maybe what you see as "last" printed message of one of the threads wasn't the "last" thread modifying the key field. You cannot say that by looking only at sterr output.
What you could do is use a synchronized setter for the key field, that increases an associated access counter whenever the field is modified and print the new value along with the modification count. This way you can avoid the problems of syserr printing and reliably determine what the last set value was. e.g. :
private long keyModCount = 0;
private synchronized long update(CopyOnWriteArrayList<Integer> possibilities, double dgeChi) {
this.keys = possibilites;
this.edgeChi = edgeChi; // how is edgeChi declared? Also volatile?
this.keyModCount++;
return this.keyModCount;
}
And inside decryptMessage:
if(chi < edgeCHI) // if the value of IOC is greater or equal than that
{
long sequence = update(possibleKeys, chi);
System.err.println("["+ sequence +"]"+ chi + " " + possibleKeys + " +");
}
To provide an answer we would need to see more of the (simplified if necessary) code that controls the thread execution.
Solution has been found. I just changed CopyOnWriteArrayList data type into ArrayList at the point where field variable gets correct key. It works as expected now.
I have a program which fetches records from database (using Hibernate) and fills them in a Vector. There was an issue regarding the performance of the operation and I did a test with the Vector replaced by a HashSet. With 300000 records, the speed gain is immense - 45 mins to 2 mins!
So my question is, what is causing this huge difference? Is it just the point that all methods in Vector are synchronized or the point that internally Vector uses an array whereas HashSet does not? Or something else?
The code is running in a single thread.
EDIT:
The code is only inserting the values in the Vector (and in the other case, HashSet).
If it's trying to use the Vector as a set, and checking for the existence of a record before adding it, then filling the vector becomes an O(n^2) operation, compared with O(n) for HashSet. It would also become an O(n^2) operation if you insert each element at the start of the vector instead of at the end.
If you're just using collection.add(item) then I wouldn't expect to see that sort of difference - synchronization isn't that slow.
If you can try to test it with different numbers of records, you could see how each version grows as n increases - that would make it easier to work out what's going on.
EDIT: If you're just using Vector.add then it sounds like something else could be going on - e.g. your database was behaving differently between your different test runs. Here's a little test application:
import java.util.*;
public class Test {
public static void main(String[] args) {
long start = System.currentTimeMillis();
Vector<String> vector = new Vector<String>();
for (int i = 0; i < 300000; i++) {
vector.add("dummy value");
}
long end = System.currentTimeMillis();
System.out.println("Time taken: " + (end - start) + "ms");
}
}
Output:
Time taken: 38ms
Now obviously this isn't going to be very accurate - System.currentTimeMillis isn't the best way of getting accurate timing - but it's clearly not taking 45 minutes. In other words, you should look elsewhere for the problem, if you really are just calling Vector.add(item).
Now, changing the code above to use
vector.add(0, "dummy value"); // Insert item at the beginning
makes an enormous difference - it takes 42 seconds instead of 38ms. That's clearly a lot worse - but it's still a long way from being 45 minutes - and I doubt that my desktop is 60 times as fast as yours.
If you are inserting them at the middle or beginning instead of at the end, then the Vector needs to move them all along. Every insert. The hashmap, on the other hand, doesn't really care or have to do anything.
Vector is outdated and should not be used anymore. Profile with ArrayList or LinkedList (depends on how you use the list) and you will see the difference (sync vs unsync).
Why are you using Vector in a single threaded application at all?
Vector is synchronized by default; HashSet is not. That's my guess. Obtaining a monitor for access takes time.
I don't know if there are reads in your test, but Vector and HashSet are both O(1) if get() is used to access Vector entries.
Under normal circumstances, it is totally implausible that inserting 300,000 records into a Vector will take 43 minutes longer than inserting the same records into a HashSet.
However, I think there is a possible explanation of what might be going on.
First, the records coming out of the database must have a very high proportion of duplicates. Or at least, they must be duplicates according to the semantics of the equals/hashcode methods of your record class.
Next, I think you must be pushing very close to filling up the heap.
So the reason that the HashSet solution is so much faster is that it is most of the records are being replaced by the set.add operation. By contrast the Vector solution is keeping all of the records, and the JVM is spending most of its time trying to squeeze that last 0.05% of memory by running the GC over, and over and over.
One way to test this theory is to run the Vector version of the application with a much bigger heap.
Irrespective, the best way to investigate this kind of problem is to run the application using a profiler, and see where all the CPU time is going.
import java.util.*;
public class Test {
public static void main(String[] args) {
long start = System.currentTimeMillis();
Vector<String> vector = new Vector<String>();
for (int i = 0; i < 300000; i++) {
if(vector.contains(i)) {
vector.add("dummy value");
}
}
long end = System.currentTimeMillis();
System.out.println("Time taken: " + (end - start) + "ms");
}
}
If you check for duplicate element before insert the element in the vector, it will take more time depend upon the size of vector. best way is to use the HashSet for high performance, because Hashset will not allow duplicate and no need to check for duplicate element before inserting.
According to Dr Heinz Kabutz, he said this in one of his newsletters.
The old Vector class implements serialization in a naive way. They simply do the default serialization, which writes the entire Object[] as-is into the stream. Thus if we insert a bunch of elements into the List, then clear it, the difference between Vector and ArrayList is enormous.
import java.util.*;
import java.io.*;
public class VectorWritingSize {
public static void main(String[] args) throws IOException {
test(new LinkedList<String>());
test(new ArrayList<String>());
test(new Vector<String>());
}
public static void test(List<String> list) throws IOException {
insertJunk(list);
for (int i = 0; i < 10; i++) {
list.add("hello world");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(list);
out.close();
System.out.println(list.getClass().getSimpleName() +
" used " + baos.toByteArray().length + " bytes");
}
private static void insertJunk(List<String> list) {
for(int i = 0; i<1000 * 1000; i++) {
list.add("junk");
}
list.clear();
}
}
When we run this code, we get the following output:
LinkedList used 107 bytes
ArrayList used 117 bytes
Vector used 1310926 bytes
Vector can use a staggering amount of bytes when being serialized. The lesson here? Don't ever use Vector as Lists in objects that are Serializable. The potential for disaster is too great.