Using java arrays - java

I have 7 lines of data in a text file (shown below).
name: abcd
temp: 623.2
vel: 8
name: xyz
temp: 432
vel: 7.6
Using regex, I was able to read this data and I have been able to print it out. Now I need to store this data in some variable. I'm leaning towards storing this data in an array/ matrix. So physically, it would look something like this:
data = [abcd, 623.2, 8
xyz, 432, 7.6]
So in effect, 1st row contains the first 3 lines, the 2nd row contains lines from 5 to 7. My reason for choosing this type of variable for storage is that in the long run, calling out the data will be simpler - as in:
data[0][0] = abcd
data[1][1] = 432
I can't use the java matrix files from math.nist.gov because I'm not the root user and getting the IT dept to install stuff on my machine is proving to be a MAJOR waste of time. So I want to work with the resources I have - which is Eclipse and a java installation version 1.6.
I want to get this data and store it into a java array variable. What I wanted to know is: is choosing the array variable the right way to proceed? Or should I use a vector variable (altho, in my opinion, using a vector variable will complicate stuff)? or is there some other variable that will allow me to store data easily and call it out easily?
Btw, a little more details regarding my java installation - in case it helps in some way:
OpenJDK Runtime Environment (build 1.6.0-b09)
OpenJDK 64-bit Server VM (build 1.6.0-b09, mixed mode)
Thank you for your help

It seems to me that
name: abcd
temp: 623.2
vel: 8
is some sort of object, and you'd do well to store a list of these e.g. you would define an object
public class MyObject {
private String name;
private double temp;
private double vel;
// etc...
}
(perhaps - there may be more appropriate types), and store these in a list:
List<MyObject>
If you need to index them via their name attribute, then perhaps store a map (e.g.Map<String, MyObject>) where the key is the name of the object.
I'm suggesting creating an object for these since it's trivially easy to ask for obj.getName() etc. rather than remember or calculate array index offsets. Going forwards, you'll be able to add behaviour to these objects (e.g. you have a temp field - with an object you can retrieve that in centigrade/kelvin/fahrenheit etc.). Storing the raw data in arrays doesn't really allow you to leverage the functionality of a OO language.
(note re your installation woes - these classes are native to the Java JRE/JDK and don't require installations. They're fundamental to many programs in Java)

You can use an array, but rather than doing a two dimensional array, create a Data Class that holds the elements and then have an array of those elements.
For example:
public class MyData {
String name;
float temp;
int vel;
}
then you could define
MyData arr[];
You could also use a List() instead of an Array, depending on if you had sorting/searching type criteria. This approach gives you a lot more flexibility if you ever add an element or if you want to find duplicates or searching.

Wrap this information
name: xyz
temp: 432
vel: 7.6
in a class of it's own.
And use whichever implementation of a List<T> you prefer.

Provided that all keys in the key-value pair that you are reading are unique, why don't you store items in a java.util.Map?
Pattern pattern = Pattern.compile("(\\w+): (\\w+)");
try(BufferedReader reader = new BufferedReader(new FileReader("data.txt"))){
Map<String, String> items = new LinkedHashMap<>();
String line = null;
while( (line = reader.readLine()) != null) {
Matcher matcher = pattern.matcher(line);
while(matcher.find()){
items.put(matcher.group(1), matcher.group(2));
}
}
System.out.println(items);
}catch(IOException e) {
System.out.println(e.getMessage());
}
The map would then contain: {name=xyz, temp=432, vel=7}
And you could easily read a particular element like: items.get("name")

I think you can rely on java Collection framework.
You can use ArrayList instead of Arrays if there is a particular sequence in the data.
Moreover if you want to store data in key value pairs, then use Map.
Note: If you need sorted values, then use ArrayList with Comparator or Comparable Interface.
If you are using Map and you need unique and sorted values, then use TreeMap

Related

Java in Android Studio: Weirdness when writing value into array of user defined class

I am writing my first app in Android Studio, I am a self-taught novice. When I write data into the subscript of an array I have created as a user-defined class the value is written into an adjacent subscript as well! Have traced to some code where I move data down one position in the array, thought I could do this in one operation, but it seems this messes something up and I need to copy each member of the class individually.
Here is my class
class LeaderboardClass
{
public String DateTime;
public String UserName;
public long Milliseconds; //0 denotes not in use
}
Here is my array declaration
LeaderboardClass[] LeaderboardData = new LeaderboardClass[LeaderboardEntries];
I want to move some data from subscript j to subscript j+1
I tried
LeaderboardData[j + 1] = LeaderboardData[j];
I thought this would copy all the data from subscript j to j+1
Then when I subsequently write to the array I (subscript i) I get the correct entry I made, plus a duplicate entry in the adjacent subscript i+1.
When I rewrite the above to:
LeaderboardData[j + 1].UserName = LeaderboardData[j].UserName;
LeaderboardData[j + 1].DateTime = LeaderboardData[j].DateTime;
LeaderboardData[j + 1].Milliseconds = LeaderboardData[j].Milliseconds;
Everything else behaves as expected. So I was wondering exactly what is happening with my first (presumably incorrect) code?
Thanks.
In Java, there's a difference between primitive values and objects (instances of classes): Primitives are stored by value whereas objects are stored by reference. This means that your code would work as you expect if you were using integers. However, since you are using a class, the array merely stores the references to those objects. Hence, when you do LeaderboardData[j + 1] = LeaderboardData[j]; you are merely copying the reference of that object. Therefore, LeaderboardData[j + 1]and LeaderboardData[j] will point to the same object.
Sidenote: If you run your program with a debugger, you can actually see this in action:
The number behind the # denotes the reference number and if you look closely, you can see that the objects at indices 8 and 9 both have the reference #716.
To fix this, I would suggest that you use lists instead of arrays as they allow you to remove and add new entries. The standard list implementation is an ArrayList but in your use-case, a LinkedList might be more efficient.
Lastly, a closing notes on your code: For variable names (like DateTime, UserName or LeaderboardData should always start with a lowercase letter to distinguish them from classes. That way, you can avoid lots of confusion - especially because Java also has a built-in class called DateTime.

Parsing a string into different variable types

Relatively new to programming here so I apologize if this is rather basic.
I am trying to convert string lines into actual variables of different types.
My input is a file in the following format:
double d1, d2 = 3.14, d3;
int a, b = 17, c, g;
global int gInt = 1;
final int fInt = 2;
String s1, s2 = "Still with me?", s3;
These lines are all strings at this point. I wish to extract the variables from the strings and receive the actual variables so I can use and manipulate them.
So far I've tried using regex but I'm stumbling here. Would love some direction as to how this is possible.
I thought of making a general type format for example:
public class IntType{
boolean finalFlag;
boolean globalFlag;
String variableName;
IntType(String variableName, boolean finalFlag, boolean globalFlag){
this.finalflag = finalFlag;
this.globalFlag = globalFlag;
this.variableName = variableName;
}
}
Creating a new wrapper for each of the variable types.
By using and manipulating I would like to then compare between the wrappers I've created and check for duplicate declarations etc'.
But I don't know if I'm on the right path.
Note: Disregard bad format (i.e. no ";" at the end and so on)
While others said that this is not possible, it actually is. However it goes somewhat deep into Java. Just search for java dynamic classloading. For example here:
Method to dynamically load java class files
It allows you do dynamically load a java file at runtime. However your current input does not look like a java file but it can easily be converted to one by wrapping it with a small wrapper class like:
public class CodeWrapper() {
// Insert code from file here
}
You can do this with easy file or text manipulations before loading the ressource as class.
After you have loaded the class you can access its variables via reflection, for example by
Field[] fields = myClassObject.getClass().getFields();
This allows you to access the visibility modifier, the type of the variable, the name, the content and more.
Of course this approach presumes that your code actually is valid java code.
If it is not and you are trying to confirm if it is, you can try to load it. If it fails, it was non-valid.
I have no experience with Java, but as far as my knowledge serves me, it is not possible to actually create variables using a file in any language. You'll want to create some sort of list object which can hold a variable amount of items of a certain type. Then you can read the values from a file, parse them to the type you want it to be, and then save it to the list of the corresponding type.
EDIT:
If I were you, I would change my file layout if possible. It would then look something like this:
1 2 3 4 //1 int, 2 floats, 3 booleans and 4 strings
53
3.14
2.8272
true
false
false
#etc.
In pseudo code, you would then read it as follows:
string[] input = file.Readline().split(' '); // Read the first line and split on the space character
int[] integers = new int[int.Parse(input[0])] // initialise an array with specefied elements
// Make an array for floats and booleans and strings the same way
while(not file.eof) // While you have not reached the end of the file
{
integers.insert(int.Parse(file.ReadLine())) // parse your values according to the size which was given on the first line of the file
}
If you can not change the file layout, then you'll have to do some smart string splitting to extract the values from the file and then create some sort of dynamic array which resizes as you add more values to it.
MORE EDITS:
Based on your comment:
You'll want to split on the '=' character first. From the first half of the split, you'll want to search for a type and from the second half, you can split again on the ',' to find all the values.

Define an array and pass each point 2 values?

I want to define a grid in which I specify an (x,y) coordinate for each point in the grid. So I want to do something like this:
int [][] pt;
for (x=0; x<numX; x=x+1) {
for (y=0; y<numY; y=y+1) {
pt[x][y] = {xval, yval};
}
}
The reason why is because I am mapping the values of an orderly grid to a disorderly grid. The above code of course causes an exception (unexpected token "{").
What is the best way to do what I'm trying to do? Thanks.
Two things:
You havent initialized your array (maybe you did just didnt put in code)
You are trying to put two values into a place where only one can be held.
Initialize your array like this (if you didnt)
int[][] pt = new int[numX][numY];
To store both values in the array you will need to use an object. The java Point class would be an example of something you could use
Point[][] pt = new Point[numX][numY];
for (x=0; x<numX; x=x+1) {
for (y=0; y<numY; y=y+1) {
pt[x][y] = new Point(xval, yval);;
}
}
You basically want to store a fixed number of values inside every array cell?
Then you are limited with 2 major cases:
Use an object
Java doesn't have user defined value types, so you are forced to use full-blown objects on the heap (with little hope that JVM will be very clever and optimize it, but chances are near zero), be it an array, or any other class.
If both of your values are less than 64 bits, you can pack them in built-in primitive type (such as long) using bitwise arithmetic. (You must be very careful here)
ints are 32 bit, so you can pack 2 ints in 1 long.
pt[x][y] = {xval, yval} is illegal, pt[][] is a double dimensional array. It only can store one value. Just like this pt[x][y] = value
You may try java map.

How to deal with memory efficiency of lots of small objects in Java

I have an application which takes data from a file and stores it for later use. Each line in the file corresponds to one object Foo, which contains n pairs of Bar objects which are made of a single character String, each with a distinct Name. So I store this data like so:
Foo extends HashMap<Name, Pair<Bar, Bar>>
where Pair<A, B> is my own class which just stores 2 values and provides some methods (equals, hashcode etc).
The problem I have encountered is that when I store n=114 (this just happens to be the number in my test data) Pair objects in my Foo it should have a retained size of not much more than 228 bytes, when in fact it is more like 25kbytes. This means when I have ~1000 Foo objects I need 25MB of memory rather than 228kB, which is not really acceptable. (Note: the keys for each Foo object are the same, fooOne.keySet().equals(fooTwo.keySet()))
I am using VisualVM to profile my application, and when I delve into an instance of Foo I see:
Field Type Retained
-
this Foo 24750
...
v table HashMap$Entry[] 24662
v [0] HashMap$Entry 200
v value Pair 156
v first Bar 60
...
> code String 36
v second Bar 60
...
> code String 36
v key Name 72
...
> name String 36
> [1] HashMap$Entry 200
> [2] <HashMap$Entry> -
...
> [233] HashMap$Entry 600
...
> [255] <HashMap$Entry> -
So as you can see all the useful information is being surrounded by lots of useless (to me) data. If I had fewer, larger objects with the same data in I can see my useful:useless ratio would be better, but I can't see how I can implement this in any other way. Is there some other way I can store my data, but still be as convenient and easy to use as this?
EDIT
My application will need to be scalable to upwards of 6000 Bar instances and maybe as many Foo instances.
I'm not entirely sure that I get your question right but in this situation using Flyweights may do the trick.
Flyweight pattern
I think a lot of your problem is just object oriented code in general, and Unicode conversion specifically.
In Java a character in a string requires two bytes to store. So at the very least you can expect to double your memory usage versus keeping a file on the drive.
Each object, each little string is going to require a word worth of information because of the pointer the JVM needs to point to your object. So each pair of data is a word for the key and a word for the value plus the actual size of each. Now these pointers get added to the hash, which uses a word to point to itself, and several words to point to the entryset. And so it goes. This is object oriented programming.
Now you could change your code to store the pair as a simple char[2]. This would cut down on your memory foot print. Then when you want to interact with it, you could wrap the array with a Pair object.
You can try to drop the Bar and Pair objects and store a pair of as simple String object ,e.g. "ab" (where "a","b" currently correspond to a Pair made of Bar("a") and Bar("b"))
Probably use the Flyweight patterns to share the common names of all Foo objects, since you have fooOne.keySet().equals(fooTwo.keySet())
You say:
I have an application which takes data from a file and stores it for
later use
and later (in a comment)
I've been asked to make it as memory efficient as possible
I suspect your most memory efficient solution is to store the file and parse it upon request, rather than parse and store in advance. But do you really want to do this and suffer the related performance costs ? I don't think your memory issues are particularly huge, but (as stated by others) I would investigate the flyweight pattern.
Take a look here. You'll see that you need quite a lot more bytes than you think to store a class (string or other) in the JVM's heap.
36 bytes for a 1 character string sounds quite right, as you need to store a lot of metadata for the object that holds the character (be sure to account for UTF encoding) plus the string class overhead.

reading data from Matlab into Java

I'm trying to read a matrix produced in Matlab into a 2D array in java.
I've been using jmatio so far for writing from java to a .mat file (successfully), but now can't manage to go the other way around.
I've managed to import a matrix into an MLArray object using this code:
matfilereader = new MatFileReader("filename.mat");
MLArray j = matfilereader.getMLArray("dataname");
But other than getting its string representation I couldn't manage to access the data itself. I found no example for this or documentation on the library itself, and I actually wrote a function to parse the intire string into a double[][] array but that's only good if the matrix is smaller than 1000 items...
Would be grateful for any experience or tips,
thanks,
Amir
matfilereader.getMLArray has several subclasses to access different kinds of data in MLArray object.
To represent double array you can cast MLArray to MLDouble:
MLDouble j = (MLDouble)matfilereader.getMLArray("dataname");
I'm not familiar with that tool, but it's pretty old. Try saving to an older version of *.mat file and see if your results change. That is, add either the '-v7.0' or '-v6' flag when you save you r*.mat file.
Example code:
save filename var1 var2 -v7.0
or
save filename var1 var2 -v6

Categories

Resources