While loop with inner assignments causing checkstyle errors - java

I'm going through my code to make sure it conforms to CheckStyle standards.
I personally feel that the rule "No Inner Assignments" makes the code more complicated to understand (you have to look in 3 places instead of 1).
Is there some way that I could preserve my single area by creating a {} block within the while loop to perform my assignments and return a boolean?!
What are your opinions?
File file = new File("C:\\test.txt");
FileInputStream fileInputStream = new FileInputStream(new FileInputStream(file));
// Inner Assignment
while ((int i = fileInputStream.readLine()) != -1)
{
//
}
// No Inner Assignment
int i = fileInputStream.readLine();
while(i!= -1)
{
//
i = in.readLine();
}
I encounter similar issues when I require a while loop which assigns a combination of some variable using, for example the ++ operator.
Would this for loop be considered a better alternative (it does comply with checkstyle)
for (int i = fileInputStream.readLine(); i != -1; i = fileInputStream.readLine())
{
//
}

You can rewrite your loop as an infinite loop with a break in the middle, like this:
while(true) {
int i = fileInputStream.readLine();
if (i == -1) break;
}
Note that i can be moved inside the loop: the only value that it can have upon exiting the loop is -1, so there is no reason to keep the variable visible outside the loop.

Related

Count elements of a list using While loop in java

I am passing some parameters in the URL and then I add them in a list. My list has a limit of 5 elements. So if someone adds 6th element in the URL the list would simply ignore it. So I am trying to use a counter but the logic is not working as desired. I am using While loop to achieve this. So if list size is smaller than 5 set the agencyCds otherwise just return the list.
private List<IUiIntegrationDto> generateViewIntegrationReportData(ESignatureIntegrationConfig eSignConfig) throws Exception {
int counter = 1;
if(eSignConfig.getAdditionalAgencyCds() != null ) {
List<String> combinedAgencyCds = new ArrayList<String>();
for(String agencyCd : eSignConfig.getAgencyCd()) {
combinedAgencyCds.add(agencyCd);
}
StringTokenizer token = new StringTokenizer(eSignConfig.getAdditionalAgencyCds().toString(), StringConstants.COMMA);
while(token.hasMoreTokens()) {
combinedAgencyCds.add(token.nextToken());
}
while(combinedAgencyCds.size() < 5) {
counter = counter + 1;
eSignConfig.setAgencyCd(combinedAgencyCds);
}
// eSignConfig.setAgencyCd(combinedAgencyCds);
}
List<IUiIntegrationDto> intgList = getUiIntegrationManager().retrieveUiIntegrationReportData(eSignConfig.getAgencyCd(), eSignConfig.getCreatedDays(),
eSignConfig.getLob(), eSignConfig.getTransactionStatus(), eSignConfig.getAccounts(), eSignConfig.getSortKey(), eSignConfig.getSortOrder());
return intgList;
}
I am not completely sure about this logic if it is correct or if there is nay better approach.
Thanks
Try this instead of the last while in your code:
if(combinedAgencyCds.size() <= 5) {
eSignConfig.setAgencyCd(combinedAgencyCds);
} else {
eSignConfig.setAgencyCd(combinedAgencyCds.subList(0, 5));
}
The full combined list will then be used if it is less than 5 in size. Otherwise, only the first 5 elements are used.
Edit: Or even better:
eSignConfig.setAgencyCd(combinedAgencyCds.subList(0, Math.min(5, combinedAgencyCds.size())));
Ok so let's break down what your code is currently doing.
int counter = 1;
while(combinedAgencyCds.size() < 5) {
counter = counter + 1;
eSignConfig.setAgencyCd(combinedAgencyCds);
}
This snippet of code has a couple things wrong best I can tell. First, this loop has the possibility of running forever or not at all. Because combinedAgencyCds is never being manipulated, the size won't ever change and the logic being checked in the while loop never does anything. Second, there's a more efficient loop for doing this, assuming you don't need the counter variable outside of its usage in the while loop and that is using for loops.
Example syntax is as follows:
for (int i = 0; i < combinedAgencyCds.size(); i++) {
if (i < 5) {
// Do your logic here.
}
else {
break; // Or handle extra values however you want.
}
}
Notice there is no need for the explicit declaration for a counter variable as "i" counts for you.
Now in your actual logic in the loop, I'm not sure what the setAgencyCd method does, but if it simply sets a list variable in the eSignConfig like it appears to, repeating it over and over isn't going to do anything. From what I can see in your code, you are setting a variable with the same value 5 times. If you need any more explanation just let me know and I will be happy to revise the answer.

Java, repeat If statement if the condition was false

Simplified, I basically have an if statement like this:
if(A[random]==1)
A[random]=0;
else
continue;
Now I know the 'continue' is for loop statements and this won't work, but I wanted something after the else that if indeed the else(basicaly the condition was false) was activated it repeated the first if(A[random]==1) statement.
You can use a while statement instead:
while (A[random] != 1) {
A[random] = 0;
// generate a new random...
}
You can try below recursion code and see if this resolve's your query
public class Test {
public void continueIf(){
if(A[random]==1)
A[random]=0;
else {
continueIf();
}
}
public static void main(String[] args) {
new Test().continueIf();
}
}
Please note if, if condition is not satisfy then it will lead to stackoverflowerror. That too it depends on the size of JVM memory. check this link for more details on stackoverflow error.
The if/Else statement won't work by itself with looping through an array. I suggest sticking it in either a For loop or a While loop. The loop will search the array and the if/else statement will check the index for the condition provided. I would also get rid of else too. You don't really need that part just the if.
A for loop in the most basic example would look something like this:
for(var i = 0; i < SIZE; i++)
{
if (A[i] == 1)
A[i] = 0;
}
SIZE would be the size of your array
random = ...; // get first random number
while (A[random] != 1) {
random = ...; // get new random number
}
A[random] = 0; // now is 1, switch it to 0
This should work.The other answers have described while and recursion so i am
also adding a do while loop.
do{
//generate the random number
}while(A[random]!=1)//The loop iterates till the condition A[random]!=1 is satisfied
A[random]==0;//changing the bit to 0
Please note that if there is no bit =1 in the array then this solution will fail because you are generating indexes randomly.
So if the array has no element =1 then it keeps on checking the indexes repeatedly and generates infinite loop.
Hope it helps.happy coding!!

How do I branch into a specified part of a loop?

int a = 0;
int b = 0;
int c = 0;
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 6; i++) {
b = sc.nextInt();
a =+ b;
c =+ (a + 1);
if (c < 20) {
i = 2;
}
}
if I have lines numbered from 0 to 6 inside the loop, the loop would be
so if c is less than 20, it repeats the operation "c=+(a+1);" until it breaks out of the loop by c>=20.
this is a simplified code from my program, mine is GUI. every time I run the code, it freezes.
use c+= instead of c=+. try that, cheers!
and b+= instead ofb=+.
You can tag a loop and do break or continue instructions, but you need design the flow, it is not possible to go into specified line, because java don't use goto instruction. You can only switch the flow inside loops by those instructions.
myloopTag:
for (...; ...; ...) {
// and you can break current loop by:
break;
// or specific (outer) loop by
break myloopTag;
// you can also use 'continue' to go to the start of the loop and increment again
continue;
// or to 'continue' at a label:
continue myloopTag;
}
You're probably very new to the language. Welcome!
If I understand your description of your intent properly, you want your code to exit the loop when c>=20. Based on your description of numbering your lines and the fact that you have the statement:
if(c<20){
i=2;
}
it seems that you think that the iterator i in the for loop is related to the line that will be executed*. This is not the case. The iterator i is a variable that simply holds an integer (just like a, b, and c in your code).
I suggest you take a look at a tutorial on for loops. It might be helpful for you to review other language basics as well, like how control flow works (this may be a better one to start with, actually).
*This guess at your intent is further supported by you counting that there are 6 lines and that your loop goes up to 6.

My object cannot be initialized because of the "else if" loop for some reason

I'm trying to add three kinds of monsters into an array by initializing my Monster-object based on the modulo. (I'm just a beginner so bear with me).
for (int i=0; i<nrofMonsters; i++) {
Monster m;
if (i%2==0) {
m = new Vampire("Vamp-"+i);
} else if(i%2==1) {
m = new Ghost("Ghost-"+i);
} else if(i%3==2){
m = new Demon("Demon-"+i);
}
monsters.add(m);
}
ERROR MESSAGE: variable m might not have been initialized.
The error message is pretty clear: there are possible execution paths throughout your code that won't lead to an assignment of a specific value into m before it is being accesses in the monsters.add(m); statement.
Specifically, there's no final else assigning some other value in the if-else if chain:
if (i%2==0) {
m = new Vampire("Vamp-"+i);
} else if(i%2==1) {
m = new Ghost("Ghost-"+i);
} else if(i%3==2){
m = new Demon("Demon-"+i);
}
else {
m = …whatever…; // or, handle this as an error
}
monsters.add(m);
Note that the compiler (apparently) isn't smart enough to understand the conditions in ifs and hence can't tell the else part isn't necessary.
I think you, in fact, wanted something like this:
if(i%3==2){
m = new Demon("Demon-"+i);
} else if (i%2==0) {
m = new Vampire("Vamp-"+i);
} else {
m = new Ghost("Ghost-"+i);
}
The if else ladder goes from top to bottom. When you delete based on modulo 2 you can have only 2 outcomes 0 or 1. Therefore you will never reach i%3. You can delete everything based on 3 and you will have 3 outcomes.
As mentioned below I don't believe it is an init issue - can you share the language you are writing on.(And do check the inheritance tree - there can be some nasty mistakes there, when you are a beginner)
The variable 'm' is a local variable .
It is a must that local variables must be initialized.
Else it must it lead to compilation error.
A simple assignment like the below one will resolve the issue:
Monster m = null;
Though the above assignment will lead to a NullPointerException, since the code might not reach any of the 'if' or 'else if' constructs.
Thus it is best to add the 'else' construct to ensure that the code runs successfully.

Java try-with-resources syntax irregularity

So I was looking through some of the new features of java 7, including the try-with-resources bit.
I understand how it works and everything, I just noticed that the syntax used to specify the resources is a little odd.
try
(InputStream fis = new FileInputStream(source);
OutputStream fos = new FileOutputStream(target))
{
// stuff
}
}
catch (Exception e) {
// stuff
}
Specifically the definition of resources:
try (InputStream fis = new FileInputStream(source);
OutputStream fos = new FileOutputStream(target))
Is there any other place in java where separating statements within a parenthesis block is valid?
The only other time I can think of is a for loop
for ( ; ; )
but that's not quite the same since there has to be exactly 2 ;s, and statements are separated with a , as in
for (int i = 1, j = 100; i <= 100, j > 0; i = i-1, j = j-1)
So my question is, where did this syntax come from? Is there a reason the statements are ; delimited instead of , delimited? Is there even another comparable language that has a similar use of ; separated statements inside of a () block? I can't think of an example in java, C, or python.
In general, statements are terminated with semicolons in Java. Note that try-with-resources differs from an assignment like int i = 1, j = 100; because it doesn't require that each thing being initialized be of the same type. It's really just a series of assignment statements wrapped in parentheses.
That said, I don't think there really needs to be any precedent for using a certain syntax if it's easily understood.
Well, it doesn't have the semicolons, but Common Lisp has several constructs that follow this pattern. For example, to bind some values to variables in a limited scope (essentially what the "try with resources" is doing):
(let (x 5) (y 10) (z 100)
(...))
It has similar stuff for condition (exception) handling, and you can also write your own constructs as needed that would probably look the same. If you imagine the (x 5) as int x = 5; you can see the parallel.

Categories