Interpreting Text Files and using Strings as Variables - java

public void readFile()
{
while(fileReader.hasNext())
{
String blankClarification1 = fileReader.next();//Why Java Why?!
Carthage_Independent_Status = Integer.parseInt(fileReader.next());
String blankClarification2 = fileReader.next();
Carthage_Stability = Integer.parseInt(fileReader.next());
String blankClarification3 = fileReader.next();
Carthage_Ruler_Name = fileReader.next();
Basic text file interpretation. However it is inefficient and time consuming my question is this? is there a way to take the name of a variable from a text file and its value then make them equivalent in such a way that the variable does not have to be specifically named in the interpretation(but rather declared earlier) and the reader takes the variable name and sets it equivalent to the value next to it?
Below is the text file
Carthage_Independent_Status 0
Carthage_Stability 100
Carthage_Ruler_Name Dido
Of course there is more in it however is it possible to have something like this?
String Variable = fileReader.next();
String Value = fileReader.next();
Variable = Value;
Is there a way to program this in such a way that it sees Variable not as a string, but as a variable and thus saves time and effort? I have seen some threads regarding turning a string into a variable by mapping it, yet nothing I have tried has had the desired effect. I believe there is such a method in PHP, but then again this is Java. If any clarification of the question is needed I'll be happy to oblige I'm just naturally bad at articulating myself.

Question: is there a way to take the name of a variable from a text file and its value then make them equivalent in such a way that the variable does not have to be specifically named in the interpretation(but rather declared earlier) and the reader takes the variable name and sets it equivalent to the value next to it?`
Yes, you can use Map<String, String>
Question: Is there a way to program this in such a way that it sees Variable not as a string, but as a variable and thus saves time and effort?
1.If your variables are basically primitive types or String, you can have some util methods. Like
class Configuration {
Map<String, String> properties; // load your files into this map at first
public String get(String key) { // if the value is string type
return properties.get(key);
}
public float getFloat(String key) { // if the value is float type
if (properties.containsKey(key)) {
return Float.parseFloat(properties.get(key));
} else {
return DEFAULT_VALUE; // the default value of the key "key"
}
}
public int getInt(String key) { // if the value is int type
}
}
There's an in production example, take a look at hadoop-common's Configuration.java
If you want to save variables of more complicated types into file, and read variables from file, you need serialization/deserialization toolkits. gson library would be a good start. You pre-define your Configuration class, and just save your configuration as json file, and load your Configuration class from file.

Related

How to get the values of specific fields in a Map<String, Object>

I have something like:
Map<String, Object> hashMap;
When I do something like:
hashMap.get("binary"), I get value as: {size=5642, name=abc}
Here key is binary and value is an Object of Type Object and is {size=5642, name=abc}
Note the values dont belong to a particular class.
In Python I can do something like hashMap["binary"]["size"], was wondering what would be the equivalent in java
How do I get the value of size directly without parsing the above string?
The value is not of Type Object, but of some type that extends from Object (in java everything extends Object implicitly). Let's call it "X"
Now, it doesn't work like python because unlike python java doesn't have that dynamic nature.
{size=5642, name=abc} is probably a string representation of that type X. This is what you see in a debugger or maybe when trying to print the value on console with System.out.println or something.
Now first of all figure out which type is it:
Object value = hashMap.get("binary")
System.out.println(value.getClass().getName());
It will print the class name
Then check the source of that class, probably it looks like this:
public class X {
private final int size;
private final String name;
... // constructor, other stuff maybe
// these are called "getters" in java world
public int getSize() {return size;}
public String getName() {return name;}
}
From that point you have 2 ways to get the size:
Object value = hashMap.get("binary");
int size = ((X)value).getSize(); // This is called downcasting
The drawback of this method is that you don't utilize the power of generics
So the better option is a refactoring if its possible of course:
Map<String, X> hashMap = ...
X value = hashMap.get("binary");
value.getSize();
One final note:
If it happens that the value is of type String, you won't be able to get the size other than parsing the value with regular expression or something. In this case consider a refactoring as a better option.

Is there a way to match a String with a method?

As far as I've researched, there's no way to match a String with a variable. probably I'm using the wrong word, here's what I mean by matching:
String grade="a";
double a=4.0;
And there's no way to associate the value of String grade with double a.
Similarly, what I want to do is associating value of a String with a method. Maybe I'm on the wrong track, let me briefly explain what I'm trying to achieve:
In the class player, there's a String name() method that returns This.name. There's no graphical design, and the only way for user to communicate with the program is typing. Basically, when person types name, I want name method to be ran. I'm pretty new, and the only way I can think of doing it is using a bunch of if statements, and adding another if statement for each method I add does not sound right to me.
Note: The reason I need String to be associated is because I'm going to use javax.swing.JTextArea to get input from the user, which returns String.
Thanks in advance
Yes. It's called a Map.
Here's some sample code of how to use one:
Map<String, Double> map = new HashMap<>();
map.put("grade", 4.0);
double a = map.get("grade");
If you want to store a variety of value types use Map<String, Object>, but you'll have to make unsafe casts when retrieving and using the values returned from get().
Java is not a dynamic interpreted language like Python or Perl.
To associate arbitrary strings with values you should use a Map<String,ValueClass> where ValueClass is the value to associate, such as Integer, Float, BigDecimal or your own value class.
Because grades are usually fixed from A to F, I would use an enum to map each grade to a numeric value:
enum Grade {
A(4.0), B(3.0) // etc...
private double val;
private Grade(double val) {
this.val = val;
}
public double getVal() {
return val;
}
}
Then use Grade.A.getVal() when you need the numeric value of the A grade.

create variables dynamically, Data Types of java Variables

As we know variables are of different data types, but which data type are their names of?
As it seems they are String, but if they are String then this should be allowed:
int i=6;
String [] arr+i;
...as we can add an int to a String.
So if these are not String then what are they?
And if we want to create variable names dynamically how can we create it?
By dynamically I mean whenever the user clicks on a specific JComponent, a new variable is created, like:
int i=0;
//on first click
String str+i; ///str0
i++;
///on 2nd click
String str+i; ////str1
///i++;
How can I do it?
You can not create dynamic variables in Java because Java isn't a scripting language. YOu need to create variables in source code. But Java provides other ways to do this.
You can use arrays or Map<String, String> etc for this purpose.
Map<String, String> map= new HashMap<>();
int i=0;
while(true) {
// you can use whatever condition you need
details.put("key" + i, "val: "+i);
i++
// some condition to break the loop
}
Java identifiers are not of any type and definitely not String. You can't do this in java, instead, you use a data structure to use these values like ArrayList<String>and store the nth String in the nth index of the data structure like so:
ArrayList<String> strings= new ArrayList<String>(); // Create a new empty List
strings.add(index, string); //add string at index position of the List; can be replaced with strings.add(string) if the strings are being sequentially added
CONSIDER THIS:
public class Test {
public Test() {
}
public static void main(String[] args) {
// GenericType<Integer> intObj;//creates a generic type for integers
//String type
GenericType<String> strObj=new GenericType<String>("My data");
System.out.println("Value is " +strObj.getValue());
}
}
class GenericType<GT>{
GT obT;
GenericType(GT o){
obT=o;
}
GT getValue(){
return obT;
}
void showType(){
System.out.println("Type of GT is " +obT.getClass().getName());
}
}
GT is the name of a type parameter. This name is used as a placeholder for the actual type that will be passed to GenericType when an object is created. Thus, GT is used within GenericType whenever the type parameter is needed. Notice that GT is contained within
< >. This syntax can be generalized. Whenever a type parameter is being declared, it is specified within angle brackets. Because Gen uses a type parameter, Gen is a generic class, which is also called a parameterized type.
as mentioned above JAVA provide you with advanced generic classes such as ArrayList, Vectors, Hashmaps to cater for such scenarios .
previous thread similar: How to create new variable in java dynamically
Variable names do not have data types. They are merely references. They are not a String, they are not an int, they are just names. You can't dynamically declare a variable with a name derived from the name of another variable, Java does not work this way.
Java does not work this way. Other languages do but Java isn't one of them. You can't dynamically manipulate the names of variables because they are fixed at compile time. However, in some interpreted scripting languages such a thing is possible.
To be more accurate if they are fixed to be anything at all they are fixed at compile time. If java is not compiled in debug mode the names of the variables cease to be at all. They just become addresses of memory locations.
See this for details: Can I get information about the local variables using Java reflection?
Firstly variables can be categorized into two. primitives (standard ) types such as int, float,double, char,boolean, byte... and non-primitives(user defined)types such as String, Integer, Float, Double. String type fall under non primitive , its a class provided by java.lang Api such that when you create a string variable you are indeed creating an object EX String str; str is an object it can as well be declared as String str=new String();
hence the string class consist of helper methods that may help to achieve your objective, you can as well use concatenation/joining of strings as follows:
class Demo{
String str;
static int i;
JButton but=new JButton("click me!");
.....
public static void actionPeaformed(ActionEvent e){
Object source=e.getSource();
str="msg";
if(source==but){
String newStr;
newStr=str+i;
System.out.println(newStr);
}
}
}
where str may contain some message/text eg from label/elsewhere for every click

Can I print out the name of the variable?

I have created a no. of constant variables, more than 1000, those constants are unique integer.
public static final FOO 335343
public static final BAR 234234
public static final BEZ 122424
....
....
....
Is there a way to print out the FOO, BAR and BEZ, the variable of the names in Java?
I am not familiar with java reflection. I don't know if that helps.
if ( FOO == 335343)
---> output "FOO"
if ( BAR == 234234 )
---> ouptut "BAR"
....
Actually asking this question behind is that I want to write log into the file
say
System.out.println("This time the output is " + FOO);
and the actual output is
This time the output is 335323
I want to know which variable comes from 335323.
Is there any other way apart from putting those variable and its associate constant into hashMap?
Thanks
There are some 'special case' that u can have workaround for this (which is told by other), but the most important question is: why would you want to do this (printing out variable name)?
From my experience, 99.9% of similar questions (how to print variable name? how to get variable depends on user inputting variable name? etc) is in fact raised by beginner of programming and they simply have made incorrect assumptions and designs. The goal they are trying to achieve normally can be done by more appropriate design.
Edit
Honestly I still do not think what you are trying to do is the way to go, but at least I think the following is a workable answer:
It is more or less a combination of previous answer:
(Haven't try to compile but at least it give u an idea)
class Constants {
public static final int FOO = 123;
public static final int BAR = 456;
private static Map<Integer, String> constantNames = null;
public static String getConstantName(int constVal) {
if (constantNames == null) {
Map<Integer, String> cNames = new HashMap<Integer, String>()
for (Field field : MyClass.class.getDeclaredFields()){
if ((field.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) != 0) {
&& int.class == field.getType()){
// only record final static int fields
cNames.put((Integer)field.get(null), field.getName());
}
}
constNames = cNames;
}
return constantNames.get(constVal);
}
}
assuming you want to get a constant name, just do:
Constants.getConstantName(123); // return "FOO"
As I noted in my comment to the original post, I have a strong suspicion that the best solution for your current problem is to solve it in a completely different way. You seem to want to associate an int with a String, and one way to do this is to use a Map such as a HashMap. For e.g.,
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<Integer, String> myMap = new HashMap<Integer, String>();
myMap.put(335343, "FOO");
myMap.put(234234, "BAR");
myMap.put(122424, "BEZ");
int[] tests = {335343, 234234, 122424, 101010};
for (int i : tests) {
// note that null is returned if the key isn't in the map
System.out.printf("%d corresponds to %s%n", i, myMap.get(i));
}
}
}
Edit 1:
Per your recent comments and update to your original question, I take it that you have many numbers and their associated Strings involved in this program and that your need is to find the String associated with the number. If so, then you need to think re-design, that the numbers and their strings should not be hard-coded into your program but rather be part of the program's data, perhaps in a text file with one column being the numbers and the next column (separated by a space perhaps), the associated text. This way you could read in the data and use it easily in a HashMap, or data base, or really any way that you desire. This will give your project much greater flexibility and robustness.
You can use something like:
for (Field field : MyClass.class.getDeclaredFields()){
if (field.getType().toString().equals("int")){
int val = (Integer)field.get(MyClass.this);
switch (val){
case 335343:
case 234234:
System.out.println(field.getName());
}
}
}
Remember to change MyClass for your class name and that at least one instance should exist to get the value of the field. So, if you are planning on testing the code in a main method, you should change MyClass.this to something like new Myclass().
Another thing to remember is that the fields are attributes and not method variables (so it won't work if you are using this to access variables declared inside a method).
You can use enum.
If these numbers just need to be unique, you can say
public enum Yourname {
FOO, BAR, BEZ
}
and refer to the name as Yourname.FOO and the value as Yourname.FOO.ordinal(). You can use enums for if-blocks, switch-statements.
If you want to have the numbers you gave in the question, so if FOO needs to be 335343, you can create numbered enums. Have a look at is-it-possible-to-assign-numeric-value-to-an-enum-in-java and number-for-each-enum-item.
I would suggest that you print out the line number, not the variable name. That should give you enough to determine where the message is coming from. Here's more info on how to do that:
How can we print line numbers to the log in java
I had a similar problem with a long list of int variables that I had to print the name of each variable and its value (main goal was to create a text file that was going to be imported in an Excel file).
Unfortunately I'm quite new in Java programming, so the only solution that I found (probably wrong) is to use two different arrays: one String array for the String name and another Int array for the corresponding values.
For example:
int varName01, varName02, ....
String[] listNames = new String {"varName01", "varName02", .....
int[] listValues = new int {varName01, varName02, .....
for (int i=0; i<listValues.length;i++)
{
print String.format("%s %d", listNames[i], listValues[i]);
}
Probably this is not the correct way to do it, so any opinion from some Java expert would be more than welcome. Thanks!

When creating methods and passing objects as parameters, are they copied or referenced? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is Java pass by reference?
see example below... need java.io library to run...
public class BlankClass extends ConsoleProgram {
public void run() {
while(true) {
setFont("London-24");
String name = readLine("Type a name: ");
fixName(name);
/* I know that the way this is written doesn't make sense and that println(fixName(name))
* is the right way. However, I thought that when objects then the method is using the object
* (in this case a string) and not a copy of it. In other words, it is referenced.
* So if it is referenced why isn't it printing out Steven when I give it STEVEN.
*/
//println(fixName(name); this is removed to show the question.
println(name);
}
}
private String fixName(String name) {
char first = name.charAt(0);
first = Character.toUpperCase(first);
name = name.substring(1);
name = first + name.toLowerCase();
return name;
}
}
Java always passes parameters by value - but in the case of classes/objects, the value that's passed is a reference, not an object itself.
What the type involved, the value of the argument expression is copied as the initial value of the parameter. Changes to the parameter variable itself are not seen by the caller, whereas changes to the object that the reference refers to will be seen.
For example, using StringBuilder (which is a mutable type):
public void foo(StringBuilder builder)
{
builder = new StringBuilder("Change to builder");
}
public void bar(StringBuilder builder)
{
builder.append(" - appended");
}
Now:
StringBuilder x = new StringBuilder("Original value");
foo(x);
System.out.println(x); // Still prints "Original value"
StringBuilder y = new StringBuilder("Original value 2");
bar(y);
System.out.println(y); // Prints "Original value 2 - appended"
Note that when I say "the value of the argument expression", that is never an object - it's either a primitive value, or a reference.
I like to think of an analogy with houses. Suppose you have a piece of paper (a variable) with directions to a house written on it. You call a method and use that variable as the argument - that creates a new piece of paper (the parameter) with the same directions on. If the method crosses out the original directions and replaces them with some other ones, that doesn't change the first piece of paper. On the other hand, if the method follows the directions and then paints the house red, then you would see that change if you followed the directions on the first piece of paper.
EDIT: To explain your original code... no objects are being copied, but the value of name in run is being copied into fixName. You're then changing the value of the parameter in fixName when you write this:
name = name.substring(1);
You're changing it again when you write:
name = first + name.toLowerCase();
Neither of these have changed the value of name in the calling code, which is still referring to the original string.
You're then returning the new string reference here:
return name;
but your calling code is completely ignoring it, because you've just written:
fixName(name);
One way to demonstrate what's happened is to use the return value in a new variable:
String fixedName = fixName(name);
Then you could print out name (which would show the original string) and fixedName (which would show the new one).
you pass a reference, so you work with the same string, BUT you return another string, because String in java is immutable - every operation (such as subString) produce new string and if you want to perform many operations on string (such as substring, replace etc.) use a StringBuffer or StringBuilder
This does not really answer your question, but you should avoid assigning parameters (like 'name' in this case), it can be handy at times but it is generally considered a bad practice because it often leads to unreadable and hard to maintain code.
In your case the variable is both a parameter and a local variable.
In Eclipse there is a warning you can activate for this in
Preferences->Java->Compiler->Errors/Warnings->Code style->Parameter assignment
I would recommend to set the parameter 'name' final in order to enforce this.
Return another String that is based on your 'name' String and name it properly.
The goal is that anyone reading your code should be able to quickly understand what is going on by elimination (the function is private, it is static, the parameter is final...). This excludes a lot of side effects.
Search for the concept of 'pure functions' on the web. Make the method static so the person reading your code knows that there are no side effects on the instance.
Here is the new version:
private static String fixName(final String name) {
final char firstCharOfName = Character.toUpperCase(name.charAt(0));
final String fixedName = firstCharOfName + name.substring(1).toLowerCase();
return fixedName;
}

Categories