How to print Fibonacci Series in Java without using For Loop?

So my example actually isn’t using recursion. Recursion does use up stack space but that’s not exactly what’s happening here. Java’s Streams use a class called Spliterator underneath the covers that does repeated iteration on the source items. This is much closer to an infinite while loop with a break statement in the middle of it (via the limit method in my original example). I’ve also verified this is true by running my program in the debugger, setting a breakpoint on the lambda expression that computes the next pair of values, and verifying that the number of stack frames each time through is the same amount of frames:

The main benefit from using streams is being able to use language features more similar to functional programming and focusing on the concise algorithms such as how to compute the next value, rather than having to worry about loop counters, accumulator variables, etc. from more traditional procedural programming languages. Not saying procedural is bad, they both have their place, but this can be more concise and has negligible performance differences from traditional iteration.

4 Likes

He said he wants to print it without a loop and then you go ahead and use .forEach. What do you think the implementation of that looks like? It’s not any different from writing your own loop. Writing your own is actually ever so slightly faster as you don’t have to pass lambdas around places as you said too.

Why are we doing this what is the goal here?

If this is a school assignment probably the intention is to teach recursion.

Otherwise you are gonna have to pick what you care about conciness, readability or performance. Most of the time you’d want to find a balance of all 3 as you can’t actually get all 3. My recommendation would be to care about readability first. Test it and fix performance problems later. Many performance problems will end up being obvious from the get go with some experience, but not all. I would forget about conciness as a metric. If the lambda is more readable do that. But often the manual loop ends up being more readable, so then imo you should do that. Obcessing about conciceness too much you will most likely write unreadable code that does not perform well.

1 Like

OP actually said

There’s a syntactic difference between a for loop and any loop. I think you’re missing the point here. OP never asked that there not be any iteration in his program; he asked if there was a way to do it without writing a for loop.

I already addressed this above, you should scroll back up and reread it. It’s quite different from writing your own for loop.

This is entirely dependent on implementation details with the compiler. I’m just trying to educate OP of newer language features about another way to accomplish the same thing.

I get this a lot from people ingrained with the procedural programming paradigm. I actually find it quite readable because you suddenly aren’t having to track things like loop counters or accumulator variables, and it directs your focus to the important meat of the algorithm, the original starting numbers and the way that the (n+1)th number is computed from the nth number.

Another assumption about the underlying compiler. In 99.999% of circumstances this isn’t really a concern with a problem like this. You may be talking about performance gains measured in the nanoseconds. This was also not part of OP’s original question.

If you want to print without any loop at all (written by us or using a built-in framework in Java Streams) there’s always this approach which doesn’t require any looping (and I’m not entirely convinced the rounding is always accurate here either):

    private static void printFibonacciNumberFromFormula(int number) {
        double phi = (1 + Math.sqrt(5)) / 2;
        double psi = (1 - Math.sqrt(5)) / 2;

        double fib = (Math.pow(phi, number) - Math.pow(psi, number)) / Math.sqrt(5);
        System.out.println("The nth fibonacci number is " + Math.round(fib));
    }

This is all rather moot as once you can’t even iterate/recurse more than about 93 or 94 times before you overflow a long datatype because of how quickly the sequence grows.

For many things it is clean and works. Working as a c# I do not think I’m particularly a ‘procedural programmer’. But I’ve seen this a lot in c# people trying to force everything down a gigantic linq ‘thing’. Ending up a redicolously long statement (you might call it ‘enterprise linq’) because they somehow refuse that loops are even an option. When linq (or in javas case streaming API) does not have a clear answer for something you are trying to do you should not force it to do it anyways imo. Alternatively you can write your own linq extensions, but most of the time it seems people are too lazy to do that. At least that has been my experience.

Possibly, in some edge cases. But mostly those things are going to be slower. In fact afaik one of the recommendations from the C# compiler people at Microsoft if you want to maximize performance for a hot path is to ditch linq entierly and write hand crafted methods instead. It´s not going to be huge improvement. Most of the time there is no reason to worry about a few nanoseconds. But it´s very easy to have that escalate into much bigger numbers, because it´s very easy to end up using linq function that are complete overkill for what you are trying to do. Never actually had to do that…

Pretty sure for the most part it is going to be similar for java. Kotlin has an inline keyworkd for that specifically. It ends up skipping the method call and putting the function body directly inside the caller method when compiling it. In some cases that can give you the same performance as the same ends up being compiled (if the methods you are comparing are the same, more often than not this is not the case, because those methods are usually more ‘general purpose’ things than what you would write to solve your problem specifically).

Completely, agree with this. For most applications the overhead is not big enough to matter. But still worth knowing that there is one if you ever get into a situation where you need to sqeeze every drop of performance out of some code path.

Where though? I just see that he want´s to write the code ‘without a loop’ but have no idea why. Nvm, did not click on that link. Just do it every possible way I guess.

I don’t really know enough about linq to respond to this appropriately, but doing a cursory search it looks more like a SQL query and really not like a java stream at all. I think this is apples and oranges to compare these two things.

Concisely-written streams and lambda references will actually use hand-crafted methods. The one thing I see stream programmers doing a lot to make unreadable code is writing multi-line lambda expressions. The point of functional programming is functions! Put that code in a method/function and use a method reference for the lambda expression.

I think all this is good discussion but it’s outside the scope of OP’s original question. I think if you want to respond to this or have a larger discussion on the performance of newer language features, it probably deserves to have its own thread.

1 Like

It is for both. Linq for dbs and linq for local collections looks entierly equivalent in ‘your code’, but uses different parameters to express the lambda passend along to the function. In case of dbs the lambda´s you pass along, you`ll wrap in Expression<T> which will generate an expression tree that represents your lambda which can for example be converted to sql (but that does not change how the caller calls the method it looks the same but is entierly different under the hood). Normal local linq does not use expression trees. You just pass along functions. Which is the same as streaming api pretty much. Ofc, it´s a bit of an apple to oranges comparison because implementation will differ. What evaluates lazily, what does not, what methods exist, how are they implemented… etc. etc. Though, any way you put it it is the closest equivalent feature to javas streaming api that c# has and a lot of the knownledge is totally transferable.

Yes exactly. You are correct FNM. Its about reading for comprehension here. It would be impossible to do so without a type of loop or recursion. He specificed a specific kind

Yes and getting into the Orders of computation isnt really in the scope. I suspect this is a homework assignment with the goal of leading them to recurssion or your methods. Either work

1 Like

Possibly. The op was not very specific I don’t think. My main issue I have is that I don’t know why we are removing that loop. What is the goal? Is another loop fine? Or do we want to get rid off loops entierly? The ‘why’ makes a big difference here imo to coming up with a reasonably relevant answer.

In the links he posted in the second post they do it with recursion. Seems to be just ‘do it every way possible’ kinda thing.

Its a very classical example of a teacher getting ready for lessons into recursion. My post is literally ripped from the same question posed by my professor who said dont use a while or for loop.

That excercise is so common. There are trillions of the same examples online.

2 Likes

Yes, Im aware of that much.

But that is also a guess more than anything else.


Probably should just stop arguing about it… :sweat_smile:

yes unfortunately it is but the nature of the CS class teaching this is that they are low effort 1xxx and 2xxx level courses

Presumably OP has finished the assignment that called for the “Fibonacci without for loop” but is interesting to see ways to do it with loops.