Variable declaration with its name containing value from loop - java

i am php developer just started at java i want to declare dynamic variables inside a loop and for that i have to append the loop value to varaible name this is what i want .
I would like to make statement like this
for (i=1; i<6; i++)
{
String new_variable_ + i;
}
the above code does not work in java how to do it ?

what you are trying to do is not possible in java ... this language is
not that lose like php..its a type strict language

Variable declarations are declared to be static identifiers and cannot contain any computed values in java (and i venture to say this would be true in any statically typed language).
You say you can't find an associative array. Have you seen the java.util.Map interface (and it's implementations)? It is by definition an associative array:
Wikipedia: In computer science, an associative array, map, or dictionary is an abstract data type composed of a collection of (key,value) pairs, such that each possible key appears at most once in the collection.

Like I said in the comment, there's no dynamic variable in Java. At best you can do this:
HashMap variableMap = new HashMap<String,String>();
for (int i = 1; i < 6; i++) {
variableMap.put("new_variable_" + i, "some variable value");
}
Then to access them, you do:
String value = variableMap.get("new_variable_2");
Or to update it, you do:
variableMap.put("new_variable_2", "new value");

If you just want to use a string version of i within the loop, you need:
for (int i=1; i<6; i++)
{
String new_variable_ = "" + i;
//use new_variable here.
}
If you're looking for something different, I'll need some more details. Good luck!

Related

SonarQube-compliant solution, increment cell value

I am using Apache POI to create a excel form a Java POJO class.
The POJO has 65 fields which needs to be populated while creating a POJO.
One way I figured out was -
int i = 0;
hssfRow.createCell(i++).setCellValue(POJO.getField1());
hssfRow.createCell(i++).setCellValue(POJO.getField2());
hssfRow.createCell(i++).setCellValue(POJO.getField3());
.....
hssfRow.createCell(i++).setCellValue(POJO.getField65());
The drawback of the above approach is SonarQube says it is non compliant with the following reason
Extract this increment or decrement operator into a dedicated
statement
The first question is why is it not advised to use i++ here?
Also, is it advisable to declare constant from 1 to 65 in a separate Constant class and use it instead of i++ (i.e. hssfRow.createCell(Constant.ONE))?
And is there any alternative to this solution which is compliant and is a better approach?
I could be like this:
private static final Map<Integer, Function<POJO, TypeOfCellValue>> cellDataProviders = new HashMap<>();
static{
cellDataProviders.put(1, POJO -> POJO.getField1());
cellDataProviders.put(2, POJO -> POJO.getField2());
...
}
And use in code:
IntStream.range(1, cellDataProviders.size()).foreach( i -> hssfRow.createCell(i).setCellValue(cellDataProviders.get(i).apply(POJO)));
or with use of traditional for loop:
for(int i = 0; i < cellDataProviders.size(); i++){
hssfRow.createCell(i).setCellValue(cellDataProviders.get(i).apply(POJO));
}
the mapping from POJO to cell has been separated from the data population code.
IMHO, you can mark it as a false positive. The stated reasons for the issue are
It can significantly impair the readability of the code.
It introduces additional side effects into a statement, with the potential for undefined behavior.
It is safer to use these operators in isolation from any other arithmetic operators.
Given the circumstances of your current code, I'd say they are invalid. The code is perfectly readable as it is and there's no undefined behavior possible and I don't see any safety concern there.
As it is a false positive you can use #SuppressWarnings("squid:S...") or //NOSONAR:
//NOSONAR
hssfRow.createCell(i++).setCellValue(POJO.getField1());
//NOSONAR
hssfRow.createCell(i++).setCellValue(POJO.getField2());
//NOSONAR
hssfRow.createCell(i++).setCellValue(POJO.getField3());
...
However then it is more clear to slavely change the code to:
hssfRow.createCell(i).setCellValue(POJO.getField1()); ++i;
hssfRow.createCell(i).setCellValue(POJO.getField2()); ++i;
hssfRow.createCell(i).setCellValue(POJO.getField3()); ++i;
...
Does not hurt.
Playtime
One could hide the index using a vararg method.
Assuming the POJO object variable is pojo and its class Pojo.
fillCells(hssfRow, pojo,
Pojo::getField1,
Pojo::getField2,
p -> createDateCellValue(p.getField2()),
Pojo::getField4,
Pojo::getField5,
p -> f(pojo),
Pojo::getField7):
void fillCells(Row hssfRow, Pojo pojo, Function<Pojo, CellValue>... cellProviders) {
for (int i = 0; i < cellProviders.length; ++i) {
hssfRow.createCell(i).setCellValue(cellProviders[i].apply(pojo));
}
}
This is not as flexible, but would remove some repetitive hssfRow.createCell.

Change the value of instance without changing the other instance

For those who had read my first question, I think I found where the problem is. The problem is in the mutate method and especially in this instruction:
Chromosom ch=new Chromosom(); // Chromosom is a class who use hash table
Chromosom k= new Chromosom(); // Class chromosom extends hashmap <integer,parc>
k.initialise();
for(int i=0;i<l.size();i++) ch.put(i,k.get(i)); // in this instruction i think
And this is the constructor of Chromosom:
public Chromosom(){ // construct a blank chromosom
super();
this.identifiant = 0;
NbEquipeExterne = 0;
NbEquipeInterne = 0;
CoutMinimal = 0;
CoutMensuel = 0;
}
When I change the values of ch, the values of k change too?
How can I pass the k's values to ch by copy and not by reference?
First of all Java is always pass-by-value. or rather pass-by-copy-of-the-variable-value not pass by reference. You might be changing objects of Chromosom with k in the constructor.
No danger, both ch and k are separate objects.
Furthermore you can do
ch.putAll(k);
which is a nice short-cut to remember.
Caveat
If the values of the maps are stateful objects (having mutable fields to contain some changing info), then changing that field would change the field of the simgle value object in both tables.
BitSet bits = k.get(i);
bits.set(3);
// Now ch.get(i) being the same object, also has bit 3 set.
If a class has a static field, then that field is once per class, a single instance. So you could have in say Chromosome:
static String copyright;
Chromosome.copyright = "All rights reserved"; // Clearest style
k.copyright = "All rights given to the community";
ch.copyright = "MIT license";
And you would have dealt with the same single variable, with vaklue "MIT license".
About Java
A nice design decision was made in java:
If you pass a variable to a function/method, the object/value will be passed. It may never happen that the variable itself gets an other object/value. (Not the address of the variable is passed.) Java has pass-by-value, no pass-by-reference.

Having a List of an Abstract class in Java and needing to loop through the List

I'm trying to move my code from c# to java and it's the first time i'm trying to write java code.
Firstly i noticed that a List<> in c# is not as a list in java where i had to use an arrayList instead so i just changed
List<Instruments> instruments = new List<Instruments>();
to
List<Instruments> instruments = new ArrayList<Instruments>();
and that solved that.
Later on in my program i have a for loop which runs though the List (of an abstract "Instruments" class) and compares an enum (saved in .type) value which all the subclasses have. I:E
public static int HowManyOfType(InstrumentType TP)
{
int HowMany = 0;
for (int i = 0; i < instruments.Size(); i++)
{
if (instruments[i].type == TP)
HowMany++;
}
return HowMany;
}
However i'm getting the message "Array Type expected".
This problem wouldn't occur in c# because the property is stored in the abstract class and it would just do the comparison without needing to know the type of subclass that was stored.
I'm guessing that it's not that simple in java. Is there a was around this?
Thanks
Change this
if (instruments[i].type == TP)
to
if (instruments.get(i).type == TP)
Change your for loop to this.
for (Instruments eachInstrument : instruments) {
if (eachInstrument.type == TP) {
howMany++;
}
}
although without knowing what the data type of eachInstrument.type is, I can't be sure that it's correct to use ==. You may need to change this to eachInstrument.type.equals(TP).
If you are used to C# you might find lambdas in Java 8 more natural.
long howMany = instruments.stream().filter(t -> t.type == TP).count();
Unless the type is a primitive or an Enum you may need to use equals
long howMany = instruments.stream().filter(t -> t.type.equals(TP)).count();

Using variables as names for other variables in Java

Alright, I am not completely sure that I worded the title right, but I want to use an int variable to define another int to go through a method. In other words, I want to be able to have the int/name/thingy variable go through a ++ statement, and then the next variable would go through the method. Is this possible?
An int array might solve your problem. The array stores your ints ("variables"), another one runs throught the index (your ++ operation):
int[] values = loadValuesInArray(); // some magic to get the populated array
for (int i = 0; i < values.length; i++) {
myMagicMethod(values[i]); // calling the method with int values
}
If you need named variables, then you can use a map:
Map<String, Integer> variables = new HashMap<String, Integer>();
variables.put("a", 1);
variables.put("b", -10);
variables.put("c", 25);
myMagicMethod(variables.get("b")); // calls method with value from "variable" b
You can use reflection.
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
http://www.java2s.com/Tutorial/Java/0125__Reflection/Catalog0125__Reflection.htm
or see to have an idea.
Setting variables by name in Java
You almost certainly want to be using something like a Map or List (essentially a dense map with a small positive int key).
If you don't need to create a new variable with a name, stored in another variable, then reflection is a way to go.
String varName = "x";
Point2D point = new Point(15, 2);
Integer val = (Integer)Point.class.getDeclaredField(varName).get(point);
assert val == 15;
You say "I want to use an int variable to define another int" do you mean something like
int a = 0; //declare a new variable a of type int and assign it to zero
a b = 0; //declare a new variable b of type a which is an int and assign it to zero
From what you said, that is what it appears you are saying. If that is the case, I do not think you can do that. My memory says that there is a method that allows you to determine the type of an object, but to use that as a declaration of another variable... I don't know if you can do that.

creating multiple distinct identifiers in java

As an exercise (note that I am a programming student, but this is an exercise to satisfy my own curiosity, not for a graded assignment) in using instance variables, I would like to create an unspecified number of instances of a class and assign a unique name to each. My idea would be to make a loop such as:
int i=1;
while (! response.equals("quit")){
SomeClass object_i = new SomeClass();
i++;
...
}
This would allow the program to create as many instances of SomeClass as needed by the user, then be able to refer back to instance variables in each one such as:
for (i=1; i <= count; i++){
sum += object_i.nonStaticInstanceVariable;
}
There is a suggestion for unique identifier names using AtomicLong at this thread:
java for loop executes too fast gives System.currentTimeMillis() duplicate
but I am unsure of how I would refer to instance variables in particular objects created using this method. Can anybody suggest a way to do what I'm trying to do in Java?
Many thanks.
In your first for-loop, you're creating instances of SomeClass, but you're not doing anything with them. What you want to do is gather them up in some kind of collection, so you can refer to them later, like this:
int i=1;
List<SomeClass> classes = new ArrayList<SomeClass>();
while (! response.equals("quit")){
classes.Add(new SomeClass());
i++;
...
}
Now you can loop through your collection and do something useful with them:
for (SomeClass someClass : classes) {
sum += someClass.nonStaticInstanceVariable;
}
I would use a map and a universally unique identifier (UUID). See java.util.UUID for an example.
Map<UUID,SomeClass> map = new HashMap<UUID,SomeClass>();
for (int i=0;i<1000000;i++) {
UUID key = UUID.randomUUID()
map.put(key, new SomeClass());
}
Now if the user has a UUID then they can get a reference to the appropriate SomeClass
lol, you must really just be starting.
Read this- http://download.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
Most of what you have makes sense, but you need to do-
SomeClass myObject[i] = new SomeClass();
EDIT: Other people's options will work too, but you should learn to do it this way first.
You can't create instance variables at runtime (short of compiling and loading a new class)
Use an array or a Map for this
(Or use a dynamic language like Groovy that runs on the JVM, which internally will use a map-like structure)
I think you would just want to use some sort of collection such as an array or arraylist.
List list = new ArrayList();
int i=1;
while (! response.equals("quit"))
{ list.add(new SomeClass());
i++;
}
It could then be accessed by getting index in the ArrayList
list.get(index);

Categories

Resources