I just stumbled upon this question Are "while(true)" loops so bad?
They made me think what do I normally do.And to my surprise I realised that I have almost never used a while loop in my professional code(or work code) .
Front end frameworks e.g faces etc do not count.
So When should I use a 'while loop'? and
How often do you use while loop? It's is a real question please do not close as being subjective I really am after a concrete example.where it can not be replaced with a better alternate.
One place where I might use it is where you need to treat the first element of a sequence differently to the rest. That makes a foreach loop awkward, but a while loop works well:
Iterator<String> iterator = foo.iterator();
// Handle the first item specially
if (!iterator.hasNext()) {
throw new SomeException("foo shouldn't be empty");
}
SomeResult result = new SomeResult(iterator.next());
// Now deal with the rest
while (iterator.hasNext())
{
String item = iterator.next();
result.addItem(item);
}
Also I use a while loop as one of the few places where I'll also include an assignment in a condition:
String line;
while ((line = reader.readLine()) != null)
{
// Handle the line
}
or with an InputStream:
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
// Handle the buffer
}
java.util.Scanner scanner = //...
while(scanner.hasNextLine()) {
String line = scanner.nextLine();
//..do sth with the line
}
In fact every while loop can be replaced with for. But e.g. in the code above it would be less readable - and that's the point: use while when it fits better to the nature of the problem.
You should use it to loop while some condition holds true.
Simple never-stopping backend logic:
while (true) {
consumeMessage();
}
Or also
for (;;) {
consumeMessage();
}
You should use it when you dont know how many iterations will be needed.
You only know that you want to do something while your condition is met. It could be itereated 2, 100, 0... times.
Of course you can always rewrite a while loop into a for loop, but often it is uglier, meaning that parts of the for (..;..;..) are left blank - mainly the initialization. Findbugs also gives a warning in this case: similar to "simple for loop detected, rewrite it as a while loop".
The main application of the while loop is that you do not need an initialization, or want to treat the first loop iteration (e.g. first element of an enumeration) specially, in which case you do the initialization beforehand, too.
Use it when you have a main loop in your code which you want to run until something changes.
When you dont need a counter, and when you dont need to iterate over a collection (because then you need a counter).
Using a for(;whatever;) is ugly code, thats where you have to use a while.
Also the variation, do ... while allows you to do something at least once and then possibly many times.
Related
I am trying to make a Math Calculator Application. However I am wondering if there is a statement that allows you to go back to a certain line?
Let me clarify:
I am not referring to a loop. Here's a possibly scenerio: Let's say that the user has run the program and reached let's say line 54. If I have an if-else statement there, if there a way that I could make it so that "if (input = 0){go back to line 23}
Is there anything that may allow me to do this, not including a loop?
Java does not have a goto (goto is a reserved word but not used). Consider how your approach and language choice fit together. There is likely a better way to do this. Consider extracting a method or using a flag inside of a loop. Without more information, guidance will be limited.
Nope.
The goto statement exists in C and C++, which Java is vaguely similar to, but it's generally considered very bad practice to use. It makes code difficult to read and debug. Here are some correct ways to solve this problem with more structured programming:
do {
...
} while (input == 0);
private void doTheThing() { // please use a better name!
...
if (input == 0) doTheThing(); // recursion not recommended; see alternate
// method below
}
// alternate method:
do {
doTheThing();
} while (input == 0);
Why can't you use a loop?
Put your code in a function, then put in a loop that runs while input = 0.
My roommate's teacher gave them a assignment to implement string length method in JAVA?
we have thought out two ways.
Check the element,and when get the out of bounds exception,it means the end of string,we catch this exception,then we can get the length.
Every time a string is pass to calculate the length,we add the special character to the end of it,it can be '\0',or "A",etc..
But we all think this two way may can finish the assignment,but they are bad(or bad habit to do with exception),it's not cool.
And we have googled it,but don't get what we want.
Something like this?
int i = 0;
for (char ch : string.toCharArray()) {
i++;
}
The pseudo-code you probably want is:
counter = 0
for(Character c in string) {
counter = counter + 1
}
This requires you to find a way to turn a Java String into an array of characters.
Likely the teacher is trying to make his or her students think, and will be satisfied with creative solutions that solve the problem.
None of these solutions would be used in the real world, because we have the String.length() method. But the creative, problem-solving process you're learning would be used in real development.
"1. Check the element,and when get the out of bounds exception,it means the end of string,we catch this exception,then we can get the length."
Here, you're causing an exception to be thrown in the normal case. A common style guideline is for exceptions to be thrown only in exceptional cases. Compared to normal flow of control, throwing an exception can be more expensive and more difficult to follow by humans.
That said, this one of your ideas has a potential advantage for very long strings. All of the posted answers so far run in linear time and space. The time and/or additional space they take to execute is proportional to the length of the string. With this approach, you could implement an O(log n) search for the length of the string.
Linear or not, it's possible that the teacher would find this approach acceptable for its creativity. Avoid if the teacher has communicated the idea that exceptions are only for exceptional cases.
"2. Every time a string is pass to calculate the length,we add the special character to the end of it,it can be '\0',or "A",etc.."
This idea has a flaw. What happens if the string contains your special character?
EDIT
A simple implementation would be to get a copy of the underlying char array with String.toCharArray(), then simply take its length. Unlike your ideas, this is not an in-place approach - making the copy requires additional space in memory.
String s = "foo";
int length = s.toCharArray().length;
Try this
public static int Length(String str) {
str = str + '\0';
int count = 0;
for (int i = 0; str.charAt(i) != '\0'; i++) {
count++;
}
return count;
}
What about:
"your string".toCharArray().length
Is the following version of for loop possible (or a variation thereof fulfilling the purpose of shortening code with one line)?
for(String string: stringArray; string.toLowerCase()){
//stuff
}
Instead of
for(String string: stringArray){
string = string.toLowerCase();
//stuff
}
May seem like a stupid question but that one line is tiresome to write all the time when it applies to every element of the loop.
Write it like this
for(String string: stringArray)string=string.toLowerCase();
This is just as short. Also in a normal for loop for(int i=0;i<40;i++) you can use the comma operator to keep everything on one line
No, there isn't.
The trick with the enhanced-for loop is that it behaves like any other loop over a collection - you're working with the individual elements one at a time, as opposed to all at once.
Furthermore, since toLowerCase() returns a new String, as it should, it should only be called in situations where it's absolutely needed, as opposed to creating a new variable for that (unless you need it in more places, in which case it's better to move the lower-case functionality into those methods).
You should consider refactoring your code into several methods each with their own loops. One method creates a new array (or list) with transformed elements from the original list (such as applying toLowerCase() to the Strings in an array). The other methods process the new array rather than the original.
Unfortunately that's not possible. You could take a look at Google Guava, which has something like this (Predicates/Closures), but it doesn't help much in improving your code.
Cmpletely offtopic maybe, but it might help, if you would use Groovy, which is fully compatible with Java, it would be something like:
String[] stringArray = ["Lower", "Case"] as String[]
stringArray.collect { it.toLowerCase() }.each { item ->
println item
}
Which would print:
lower
case
But, like I said, this might not be a viable option in your case.
I don't think that's possible as of now. :)
I have a list I need to process. The items are either enabled or disabled. The user can choose whether or not to show disabled items.
So you have cond2 that depends on the items, and cond1 that does not. Here's the dilemma I got into: Should I use cond1 && !cond2 or !(!cond1 || cond2)? Or should I check for the cond2 (show disabled items) before the loop? I also thought (as you will see in the code I put) if I should put the cond2 before cond1, because cond2
is a boolean variable, and with "short-circuits" (lazy evaluation?), it will be faster?
My main concern was speed. If I have many items in the loop, this might be an important change.
This is code that illustrates the options:
// First Option
for (String item : items) {
doSomethingFirst(item);
if (isDisabled(item) && !showDisabled) {
continue;
}
doSomethingElse(item);
}
// Second Option
for (String item : items) {
doSomethingFirst(item);
if (!(!isDisabled(item) || showDisabled)) {
continue;
}
doSomethingElse(item);
}
// Third Option
if (showDisabled) {
for (String item : items) {
doSomethingFirst(item);
doSomethingElse(item);
}
} else {
for (String item : items) {
doSomethingFirst(item);
if (isDisabled(item)) {
continue;
}
doSomethingElse(item);
}
}
So, does the order of isDisabled(item) and showDisabled matter? Should I be checking on things before the loop? Or does the compiler optimize that? (I doubt...)
PS I don't know how I would take measurements to see actual values, if it's relevant please do.
Thanks.
In Java the expression is evaluated from left to right. With && if the first condition is false, the second one is not executed, with || if the first condition is true, the second one is not executed.
So try to put the condition that can be resolve faster in first place, in your case showDisabled.
For the third example, it looks better because you check the boolean only once but I guess it don't really change performance, a bool comparison is not really costly. You will probably have better improvement to do in other part of your code. (and for the readable aspect it's not my favorite - quite long)
If you want to measure the performance in your case use a profiler for example.
Or add in your code :
long start=System.currentTimeMillis();
//code to analyse
long timeSpent = System.currentTimeMillis()-start
You'll have to put your code in a loop, to make it relevant. And you will probably notice that Java will increase the performance after some loops ;).
Regarding readability, another good practice is to name functions and variables in their positive state. It's hard to read double negatives. Which one would you rather read?
enabled
Or
!disabled
There are some few cases though that naming things in their negative form makes sense. An example, if you will use them for terminating condition, e.g. end of file. while(!feof(fp))
But in most cases, the norm should be is to name things in their positive form, so reading code has lesser friction.
Let's see how your code looks like in positive form:
// First Option
for (String item : items) {
doSomethingFirst(item);
// if (isDisabled(item) && !showDisabled) {
if (!isEnabled(item) && showEnabled) {
continue;
}
doSomethingElse(item);
}
The readability on that code surely improved.
And even the following become readable too, the double negatives can be avoided, reading code is really merely reading it, not figuring it out too much. I once read an article that suggest that when writing code, it should be very pleasant to read too, he said reading code should not be like reading a detective novel. Reading double negatives code is like reading and deciphering a detective novel.
// Second Option
for (String item : items) {
doSomethingFirst(item);
// if (!(!isDisabled(item) || showDisabled)) {
// You can now avoid double negatives
if (!( isEnabled(item) || !showEnabled )) {
continue;
}
doSomethingElse(item);
}
In fact, the following is not merely double negative, it's a triple one:
if (!(!isDisabled(item)
isDisabled
!isDisabled
!(!isDisabled
It will take a two-pass read, or even a three-pass before you can decipher what's the intent of that code
As always with these types of questions, you should measure this to determine if this itself is your bottleneck. If it is, then I would measure the alternatives. I suspect for the above scenario that it will make next to no difference for your alternatives, especially since you'll likely be doing something much more heavyweight with the list entries (displaying them? writing them to a db or file?)
The simplest way to measure this is to generate a sizable list, record the time (say, via System.currentTimeMillis()) before you process, process, and then record the ms (or seconds) taken.
Should I use cond1 && !cond2 or !(!cond1 || cond2)? Or should I check for the cond2 (show disabled items) before the loop?
Whatever expresses your thoughts best, i.e. whatever is more readable.
My main concern was speed.
Writing speed? Refactoring speed? Compilation speed? Development speed? Reading and understanding speed? Debugging speed? Execution speed?
You can't have all at once. In no language.
I will go for the option 1, and just reverse switch
isDisabled(item) && !showDisabled
with
!showDisabled && isDisabled(item)
If isDisabled(...) is as slow as you say it is better to test the faster case first.
Now compared to the other option this is the most explicit and readable:
We do something is done for all items
we skip for items which validate some test
we do something for all other items.
It will be difficult to do more explicit. And the 3rd option is plain ugly.
I know it is a primitive question but I want to learn the smartest way.
I want to loop over the ArrayList<Integer> intList and it can be null. I have 2 ways of doing it
if(intList != null) {
for(int i = 0; i < intList.size(); i++){
System.out.println(intList.get(i));
}
}
and
for (int i = 0; intList != null && i < intList.size(); i++){
System.out.println(intList.get(i));
}
First way seems more pretty to me. What do you think? What are your implementations in that situation?
Excuse me, if it is duplicate question but I can't find one
Thanks
In this case I would choose the first implementation as well because its intent is clearer.
Generally, I would try to avoid a List (or any other Collection object, really) being null. When evaluating a List (which is suddenly and unexpectedly null) you most probably want to abort before any processing takes place so either case of looping over the collection would not occur.
We have one development rule in our company:
If a function is written that returns a list or an array, never return null! Return an empty list or an empty Array in the case where there are no elements to return.
This can be done with minimal overhead, like here:
public List<String> getNames() {
if( !loaded ) {
return Collections.emptyList();
}
...
}
If applied properly, you don't have to check for null-lists. We don't have to.
EDIT: Oh, and to come back to your question at hand: Use the forst variant, it is much clearer, and faster, because the null check only have to be done once (it might be that the compiler factors it out anyway, but in variant 1 you can be sure).
I prefer the first one, for the complete code segment will most likely to be:
if(intList != null) {
for(int i = 0; i < intList.size(); i++){
System.out.println(intList.get(i));
}
}
else {
//Do something here.
}
i preffer the first one as mostly i use the first process
To me the first option is clearer and easier to read and understand.
According to me first option should be preferred for its readability is better than second one, while the second one saves one extra line of code for you.
End of the day both are going to do same thing so its up to you, which code you want to use. I would suggest to stick to first as it is more developer friendly because of readability.
The first form is more readable - the intent is much clearer.
The first form may also be faster, since the second form says to test that intList is not null each time you go around the loop. (The JIT compiler may optimize away the unnecessary tests ... but why rely on this.)