Is it different than C or C#?
Java has one keyword, for, but it can be used in two different manner:
/* classical, C/C++ school */
for (int i = 0; i < N; i++) {
}
for-each style:
// more object oriented, since you use implicitly an Iterator
// without exposing any representation details
for (String a : anyIterable) {
}
it works for any type that implements Iterable<String> such as List<String>, Set<String>, etc.
The latter form works also for arrays, see this question for a more "phisophical approach".
The following demonstrates the syntax of a java for loop (from the for loop in Java):
class Hello {
public static void main (String args[]) {
System.out.print("Hello "); // Say Hello
for (int i = 0; i < args.length; i = i + 1) { // Test and Loop
System.out.print(args[i]);
System.out.print(" ");
}
System.out.println(); // Finish the line
}
}
Also see the Wiki entry on For loop
The only difference between java's for-loop syntax and C's is you can declare variables in the initialization field (1st section) of the loop
Related
I have a Object which contains a list of another object which contains a list of another object and so on... suppose I want to get count of nested list elements(lets say last one), what should be best approach rather than using traditional for loop in java as I have done in below example -
public static void main(String[] args) {
Statement statement = new Statement();
statement.getInvAccount().add(new InvestmentAccount());
statement.getInvAccount().get(0).getSecAccountStmt().add(new SecurityStatement());
statement.getInvAccount().get(0).getSecAccountStmt().get(0).getTransactionStatement().add(new TransactionStatement());
statement.getInvAccount().get(0).getSecAccountStmt().get(0).getTransactionStatement().add(new TransactionStatement());
statement.getInvAccount().get(0).getSecAccountStmt().get(0).getTransactionStatement().add(new TransactionStatement());
// method to count the number of TransactionStatement
System.out.println("Size of TransactionStatement is : " + count(statement));
}
private static int count(Statement stmt) {
int countOfTransStmt = 0;
for (InvestmentAccount invAcc : stmt.getInvAccount()) {
if (invAcc != null) {
for (SecurityStatement secStmt : invAcc.getSecAccountStmt()) {
if (secStmt != null) {
countOfTransStmt = countOfTransStmt + secStmt.getTransactionStatement().size();
}
}
}
}
return countOfTransStmt;
}
In Java 7 you're not going to do better than two for loops. I wouldn't bother with anything different.
In Java 8 you can use streams to flatten it out:
private static int count(Statement stmt) {
return stmt.getInvAccount().stream()
.filter(Objects::nonNull)
.flatMap(InvestmentAccount::getSecAccountStmt)
.filter(Objects::nonNull)
.flatMap(SecurityStatement::getTransactionStatement)
.count();
}
I would encourage you to get rid of the null checks. If you're going to ignore nulls, better to just expect them not to be inserted in the first place. It'll get rid of a lot of extra if checks throughout your code, I expect.
I'd also encourage you not to abbreviate your variables and methods. Spell out "statement" and "investment" and the like. The abbreviations are harder to read and the brevity isn't really a win.
Similarly, try to use more descriptive method names. countTransactions is better for the main method. And for the various getters, methods that return lists ought to be plural: "getAccounts" rather than "getAccount". Notice how the getters now match the class names; if you know the class name, you know the getter name. You don't have to guess if one or the other is abbreviated:
private static int countTransactions(Statement statement) {
return statement.getInvestmentAccounts().stream()
.flatMap(InvestmentAccount::getSecurityStatements)
.flatMap(SecurityStatement::getTransactionStatements)
.count();
}
Recursion could work in this case:
General idea below:
private int countTransactions(object t)
{
int sum = 0;
if (t == null) return 0;
for (int i = 0; i < t.getAllSub().count; i++)
{
sum += countTransactions(t.subAt(i));
}
return sum;
}
I have a repeating structure in my Java class and wanted to present the data as follows:
Peter Black
John Red
I do not know if the structure is right, because if I leave to show the color only, the data is overwritten
public class Test {
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
String[] names= {"Peter", "John"};
String[] colors= {"Black", "Red"};
for (String name: names) {
Person d = new Person();
d.setName(name);
for (String color: colors) {
d.setColor(color);
}
persons.add(d);
}
for (Person a : persons) {
System.out.println(a.getName() + "-" + a.getColor());
}
}
}
Console:
Peter-Red
John-Red
Instead of using a nested for loop, which is not what you are trying to accomplish, loop through both arrays at the same time.
if (names.length != colors.length) {
// error! not a 1:1 relationship
return;
}
for (int i = 0; i < names.length && i < colors.length; i++) {
String name = names[i], color = colors[i];
Person d = new Person();
d.setName(name);
d.setColor(color);
persons.add(d);
}
I could just do i < names.length, however that will break if both arrays are different sizes, so i < names.length && i < colors.length will make sure i never exceeds either of the two arrays' lengths.
Edit:
I think the real problem here is how you are storing your info. Why are you using two string arrays, instead of a collection containing Person objects?
Stop looping on colors array inside your names loop. A traditional index based loop should help you get the same name and color from each array:
public class Test {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
List<Person> persons = new ArrayList<>();
String[] names= {"Peter", "John"};
String[] colors= {"Black", "Red"};
for (int i=0; i<names.length; i++) {
Person d = new Person();
d.setName(names[i]);
d.setColor(colors[i]);
persons.add(d);
}
for (Person a : persons) {
System.out.println(a.getName() + "-" + a.getColor());
}
}
}
You can use the Enum like
enum Entity {
Peter("Black"),
John("Red");
private final String color;
Entity(String color) {
this.color = color;
}
Notice that your color loop is INSIDE your name loop. So for each name you are setting it's color to the first color then the second color and then you are moving on to the next name.
Your biggest problem is probably the use of the advanced for loop, it doesn't give you an index. If you start with:
for(int i=0;i<names.length;i++)
the solution will probably be obvious (and simplify your code)
(I'd give more but it looks like something you are trying to learn with so I'll try to avoid spoilers)
Re your comment--if you wish to simply create only completely filled out objects, use
for(int i=0;i<Math.min(names.length, colors.length);i++)
If you wish to create partial objects, use Math.max and handle the case inside where either array's length is less than i. It's all business logic code... define what you want to do and do it.
How to handle bad data (Not part of the original problem):
If you want to handle the cases where the arrays are unequal, if you use the "Math.max" solution above, then adding the inside of the loop could look like this:
if(names.length < i)
d.setName(names[i])
if(colors.length < i)
d.setColor(colors[i])
This way there is no exception and you are safely setting values.
But since that leaves your objects invalid, you might be better off not allowing a different number of colors and names from your user. If he enters 3 names, then throw away blank colors and keep re-prompting until you have 3 colors--then stop prompting. It's always safest to catch problems like this as soon as possible.
Another good solution, start with:
if(names.length != colors.length)
throw new IllegalArgumentException("createUsers method must have the same number of names as colors but was called with "+names.length+" names and "+colors.length+" colors")
Ensuring your parameters are correct and throwing an exception if they are not simplifies your code a LOT and is generally a very good practice.
So for example I have the following variables:
Var1, Var2, Var3, Var4, Var5 - a total of 5 variables.
All with unique data and I want to loop though them using a for loop.
//String Var1 = something, Var2 = something etc..
for (int i = 1; i <= 5; i++)
{
Var(i) = "something else";
}
//i.e I change Var(1), Var(2) etc.. to something else respectively.
To clarify further, ultimately I want to apply this method to iterate through multiple components in my program. I have a large number of components with styled names(e.g. label1, label2, label3 etc..) and want to change the value of these components without having to individually set their value.
You can do it with reflection, if the variables are defined as members of a class. For method parameters or local variables it is not possible. Something similar to this:
Class currentClass = getClass();
Field[] fields = currentClass.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
If you intend to change the value it becomes a bit more complicated as you also have to consider the type of the variable. E.g. you can assign a String to a variable of type Object but not the other way around.
I would suggest to go for an array if data type of variables are same.
You can try something like that
String[] Var = {"something","something2","something else"};
for (String var : Var)
{
System.out.println(var);
}
As long as all the variables use the same type, you can use an Array to store all of them. Then you can use a for loop to iterate through the array. Something like this:
String[] V = {"var1","var2","var3","var4","var5"};
int arraylength = V.length;
for(int i = 0; i<arraylength; i++){
System.out.println(V[i]);
}
You can't loop through (local) variables. You can use an array or a List and then loop through its elements:
for (Object item : myListOfObjects) {
// do the processing
}
Using Java 8 Arrays it is as simple as:
Arrays.stream(varArray).forEach(System.out::println);
Usage:
public class LoopVariables {
public static void main(String[] args) {
String[] varArray = new String[]{"Var1", "Var2", "Var3", "Var4", "Var5"};
Arrays.stream(varArray).forEach(System.out::println);
}
}
Try This piece of Code.
public class Main {
public static void main(String[] args) {
Insan i1[]=new Insan[5];
i1[0].name="Ali";
i1[0].age=19;
i1[1].name="Pakize";
i1[1].age=29;
i1[2].name="Kojiro Hyuga";
i1[2].age=30;
i1[3].name="Optimus Prime";
i1[3].age=40;
for (int ib=0; ib < 4; ib++) {
System.out.println("Name: " + i1[ib].name + " Age: "+i1[ib].age);
}
}
}
E.g.
I have a queue
void someMethod() {
history.add(new Sample(time, data));
...
traverse(history);
}
void traverse(Queue<Sample> history) {
for(int i=0; i<history.size(); i=i+10) {
history.get(i)... // ???
}
}
class Sample {
long time;
double data;
}
The concerns are that
I don't want to destroy this queue by calling traverse().
Traverse the queue in a given step, say 10 here.
Any simple and nice solution?
for (Sample s : history)
doStuff(s);
This is called the enhanced for-loop; you can read more about it here.
Queue implements Iterable, so a simple loop will traverse it:
for (Sample sample : history)
An Iterator is another way to do it, with more control (can destroy it if you want to), but more verbose.
If you just want to iterate, use a for-each loop or directly a for loop with an Iterator. This doesn't consume the queue.
If you need to iterate with a step, you can use this pattern. It works generally with any Iterable. Putting the skipping into a separate reusable method makes the code more clear than having two nested for loops.
public static void main(String[] args) {
Queue<Sample> history = ...
int step = 10;
for (Iterator<Sample> it = history.iterator();
it.hasNext(); skip(it, step - 1)) {
// note that we skipped 1 less elements than the size of the step
Sample sample = it.next();
// stuff
}
}
static void skip(Iterator<?> iterator, int count) {
for (int i = 0; i < count && iterator.hasNext(); i++) {
iterator.next();
}
}
LinkedList<Sample> h = (LinkedList<Sample>) history;
for(int i=0; i < h.size(); i+=step) {
h.get(i).memory ...
}
I just realized this approach, haven't tried it yet.
As nullptr pointed out, the condition for above code is that the Queue is implemented as a LinkedList. (which is my case: Queue<Sample> history = new LinkedList<Sample>();)
Need help on calling a method from main class.
I need to call a method, thus I made an object to handle it.
below I quote my main method
public static void main(String[] args) {
// TODO code application logic here
SLRatio sl= new SLRatio();
sl.clustering(apa);
}
and here's the method I need to call
public class SLRatio {
public static String [][]clustering(String[][]apa) {
System.out.println("Cluster 1");
int a = apa.length/3;
String [][] cluster1=new String [a][apa[0].length];
for (int i =0; i<a; i++) {
for (int j=0;j<apa[0].length;j++) {
cluster1 [i][j] = apa[i][j];
}
}
for (int b = 0; b < cluster1.length; b++) {
for (int c = 0; c < cluster1[0].length; c++) {
System.out.print(cluster1[b][c] + "\t");
}
System.out.println("");
}
System.out.println("\n");
return cluster1;
}
}
and I got error message:
"Cannot find symbol,Accessing static method clustering"
What can I do to solve it? I have tried to change the syntax but it didn't work.
Thank you so much.
you didn't define method Allocation() in SLRatio
Note: static method should be called with classname (to avoid confision between instance method and static)
If it is static method, you don't need to call it through instance.
SLRatio .clustering(...);
should be enough.
And it seems you forgot to implement Allocation method.
Another suggestion, java naming convention, method name starts with small case letters.
Do not use static unless you are sure it is appropriate.
This is a popular programming error, partially because eclipse keeps on suggesting to make variables and methods static when they cannot be accessed. But usually, this is not the correct solution. While it fixes the compilation problem, it often breaks the application logic.
Right now, your problem probably is that apa has type String[][], but you are passing a String[] parameter to it. So it cannot be compiled, because there is no method clustering(String[] args).
Seriously, you need to learn more Java basics. Maybe from a book.