Writing an expanding array - java

I have a piece of code that waits for data to come from a shaky network. The machine that runs the code could also go down at any moment.
So I am writing in-coming data to the disk as the program runs. If the system goes down, I would have data up to that point. I can save each data object in a separate JSON file but that would end up with hundreds of thousands of files.
What I would like to do is to append to one JSON file that can be read back as an array or list. Each time the data comes in it is written to the end without re-writing the older data. What is the best way to do that?

You can create a FileWriter, with true as the second constructor argument. This makes a FileWriter that will append to an existing file, instead of replacing it (see http://docs.oracle.com/javase/7/docs/api/java/io/FileWriter.html).

The method does not change the value of OrigArray; all it does is store a clone of a clone in it, so in effect the value isn't changed.
I think what you want is this:
public void expand() {
String[] newArray = new String[OrigArray.length + 1];
System.arraycopy(OrigArray, 0, newArray, 0, OrigArray.length);
//an alternative to using System.arraycopy would be a for-loop:
// for(int i = 0; i < OrigArray.length; i++)
// newArray[i] = OrigArray[i];
OrigArray = newArray;
}
This creates an array that has a size 1 greater than OrigArray, copies the content of OrigArray into it and assigns that array to OrrigArray. Unless you want to remember how many times expand() has been called, there shouldn't be a reason to have the variable size.

Related

What is more efficient? Storing a split string in an array, or calling the split method everytime you need it

What is going to be faster, storing a split string into an array and using this array within my program, or could I call the .split() method on the string whenever I needed an array to iterate through?
String main = "1,2,3,4,5,6";
String[] array = main.split(",");
vs
main.split(",");
whenever I need to use the input values?
I realise it will be way more readable if I were to store the string in an array. I'd just like to know if the .split() takes more computing time than using an array. Since the split method returns an array containing the split strings.
A simple example(?) loop to go with the question:
for (int i = main.length - 1; i >= 0; i--){}
vs
for (int i = main.split(",") - 1; i >= 0; i--){}
It's a trade off, like most such things in programming. If you split just once and use the array directly from then on, you'll save processing time at the expense of memory. If you split every time, you'll save memory at the expense of processing time.
One is more time efficient, the other is more space efficient.
As you can see, the split() method returns an array so behind the scenes the main.split(",") will iterate every time you call it through main String to extract the values. So it's faster to use it only once and use the result.
I would prefer to split once and keep the tokens around regardless of the size of the array. If the resulting array is large, it will be more expensive to split each time. If it is small, the resultant storage is probably not going to be a factor.
If your worried about storage for a large array, then the last time you split should also be a concern. To mitigate that, simply assign null to the array when your done and let the garbage collector do its thing.
If I were going to iterate thru an array of tokens, I would probably do it like this.
for (String token : main.split(",")) {
// do some stuff.
}
which creates the array once.

Java - Old array always is equal to new array?

I'm not very good at programming but right now, I need to do program a little Java application and I'm running into a weird problem. I've been trying to solve this for hours now.
Here's the problem:
I'm saving a small amount of my screen (20x20) to my program. I do this by looping through every pixel, saving it's RGB into an array via Java.awt.robot. With the following function, the program should save the copied image to 3 arrays (R, G and B) before getting the new area of the screen (I want to compare them later and look for changes). The one damn thing: The old arrays in which I save the data before overwriting the main arrays are always overwriting without me telling them to.
private void fillArrayData(){
oldDataR = dataR; <----- The problem is here. These arrays are now overwritten with the
oldDataG = dataG; <----- current data, just before I write stuff to dataR, G and B.
oldDataB = dataB; <----- As you see, I don't modify oldDataR, G, B later on.
scanArea.x = MouseInfo.getPointerInfo().getLocation().x;
scanArea.y = MouseInfo.getPointerInfo().getLocation().y;
for(int i = 0; i<scanSize; i++){
for(int n = 0; n<scanSize; n++){
dataR[i][n] = (rbt.getPixelColor(scanArea.x+i, scanArea.y+n)).getRed();
dataG[i][n] = (rbt.getPixelColor(scanArea.x+i, scanArea.y+n)).getGreen();
dataB[i][n] = (rbt.getPixelColor(scanArea.x+i, scanArea.y+n)).getBlue();
}
}
}
Even though I never access oldDataR, oldDataG and oldDataB later on, it everytime is equal to the dataR, dataG and dataB after this void finishes. That doesn't make sense as I'm writing new data to the three main arrays (dataR, dataG, dataB) AFTER I saved them to the oldData-Arrays. And yes, I made sure that the data which is received by rbt.getPixelColor is not the same as before.
Please help me, I'm really frustrated by now but need to keep going.
That is happening because oldDataR (and the rest) is just another variable pointing to the same array, if you want to keep the old values in the array separately, and modify the original one, you need to copy it.
This post can be helpful for copying two-dimensional arrays:
copy a 2d array in java
You are passing your arrays as references, so, in the end it is the same array in the pointers of the two variables.
Have you tried array copy?
System.arraycopy()
or
Arrays.copyOf()
Your code would look like:
oldDataR = Arrays.copyOf(dataR);
Edit
I missed the multi dimension of the arrays, just follow #khachik link suggestion so you can handle the two dimensions.

How to add an element at the end of an array?

I want to know how to add or append a new element to the end of an array. Is any simple way to add the element at the end? I know how to use a StringBuffer but I don't know how to use it to add an element in an array. I prefer it without an ArrayList or list. I wonder if the StringBuffer will work on integers.
You can not add an element to an array, since arrays, in Java, are fixed-length. However, you could build a new array from the existing one using Arrays.copyOf(array, size) :
public static void main(String[] args) {
int[] array = new int[] {1, 2, 3};
System.out.println(Arrays.toString(array));
array = Arrays.copyOf(array, array.length + 1); //create new array from old array and allocate one more element
array[array.length - 1] = 4;
System.out.println(Arrays.toString(array));
}
I would still recommend to drop working with an array and use a List.
Arrays in Java have a fixed length that cannot be changed. So Java provides classes that allow you to maintain lists of variable length.
Generally, there is the List<T> interface, which represents a list of instances of the class T. The easiest and most widely used implementation is the ArrayList. Here is an example:
List<String> words = new ArrayList<String>();
words.add("Hello");
words.add("World");
words.add("!");
List.add() simply appends an element to the list and you can get the size of a list using List.size().
To clarify the terminology right: arrays are fixed length structures (and the length of an existing cannot be altered) the expression add at the end is meaningless (by itself).
What you can do is create a new array one element larger and fill in the new element in the last slot:
public static int[] append(int[] array, int value) {
int[] result = Arrays.copyOf(array, array.length + 1);
result[result.length - 1] = value;
return result;
}
This quickly gets inefficient, as each time append is called a new array is created and the old array contents is copied over.
One way to drastically reduce the overhead is to create a larger array and keep track of up to which index it is actually filled. Adding an element becomes as simple a filling the next index and incrementing the index. If the array fills up completely, a new array is created with more free space.
And guess what ArrayList does: exactly that. So when a dynamically sized array is needed, ArrayList is a good choice. Don't reinvent the wheel.
The OP says, for unknown reasons, "I prefer it without an arraylist or list."
If the type you are referring to is a primitive (you mention integers, but you don't say if you mean int or Integer), then you can use one of the NIO Buffer classes like java.nio.IntBuffer. These act a lot like StringBuffer does - they act as buffers for a list of the primitive type (buffers exist for all the primitives but not for Objects), and you can wrap a buffer around an array and/or extract an array from a buffer.
Note that the javadocs say, "The capacity of a buffer is never negative and never changes." It's still just a wrapper around an array, but one that's nicer to work with. The only way to effectively expand a buffer is to allocate() a larger one and use put() to dump the old buffer into the new one.
If it's not a primitive, you should probably just use List, or come up with a compelling reason why you can't or won't, and maybe somebody will help you work around it.
As many others pointed out if you are trying to add a new element at the end of list then something like, array[array.length-1]=x; should do. But this will replace the existing element.
For something like continuous addition to the array. You can keep track of the index and go on adding elements till you reach end and have the function that does the addition return you the next index, which in turn will tell you how many more elements can fit in the array.
Of course in both the cases the size of array will be predefined. Vector can be your other option since you do not want arraylist, which will allow you all the same features and functions and additionally will take care of incrementing the size.
Coming to the part where you want StringBuffer to array. I believe what you are looking for is the getChars(int srcBegin, int srcEnd,char[] dst,int dstBegin) method. Look into it that might solve your doubts. Again I would like to point out that after managing to get an array out of it, you can still only replace the last existing element(character in this case).
one-liner with streams
Stream.concat(Arrays.stream( array ), Stream.of( newElement )).toArray();

More efficient for an Java Array

I have an assignment, in which we have to create a directory which stores names and an extension number. In the first part we have to store the information in just an Array. We have to be able to add an entry to the Array and also initially read a .txt file and store it in the Array. Finally it has to print the Array. I was just wondering what would be more efficient because I only started learning code the last few months and this is difficult for me.
1) Would it be better to first create an Array of size [9999] (because that is the max number of entries the directory could have because everyone has a unique four digit number). I have an INT called count which keeps a count of what the last Array[x] to be added so when I call a method like addEntry, it will add the Entry to [X+1].
The problems with this be is that from what I have read, Arrays are huge and it could have performance problems. Also I have to be able to make a 'lookup' method which should be able to search the Array for someones number by entering their name.
My other option:
2) When the file is read, it counts how many lines the file has (each entry will be on its own line) then creates an Array of the number of lines in the text file. Whenever I want to add a new Entry, I copy the Array into an ArrayList, then back to an Array with the new Entry added. However I also read that copying arrays is not so good too and in a realistic view, if someone was to use this directory they could be adding entries every day.
Aslong as I store in an Array and print the Array into a table it is all good, but what would be the best way to make the actual Array when you don't know the size? (Yes I know I can use ArrayList but its specifically said not to)
Also how would you go about deleting an Entry in the Array, if I use my way there would be a missing entry at Array[x] where x got deleted.
Thanks in advance for any replies.
It is best to initialize an array to the size that you initially need it. When you need to add items to the array after that, you can uses a memory copy rather than an object clone.
int[] arrayOne = new int[20];
int[] arrayTwo = new int[40];
System.arraycopy(arrayOne, 0, arrayTwo, 0, arrayOne.length);
This copy is actually very fast because it just makes a direct copy from memory. This is actually what the underlying code of array list does when it doubles in size.
If you want a "dynamic" sized array, you could write your own version of array list.
For example:
Starts at size 1
Doubles in size when it gets full
shifts objects on a delete using System.arraycopy()
reduces in half when a delete causes size to be less than n/3

How to avoid frequently file write in Java

I have the problem:
in a loop, each time I need to write a large string into one file(or temporary file), then process take the file as an argument for the next step.
Something along:
for(int i=0;i<n;i++){
File f = File.createTmpFile("xxx","xxx");
// write into f etc.
String result = func(f);
}
Since I think each time creating a File and writing string into it seem to be much costly, so is there any alternative methods?
If these Strings do not need to be immediately persisted to a File, you could store them in memory, some sort of Collection, e.g. an ArrayList. And when the list gets "large", say, every tenth time, write all ten at once to a file. This cuts file creation by 10X.
The danger is that if there is a crash you may lose up to 9 values.

Categories