10

My Code:

List<Integer> ints = Stream.of(1,2,4,3,5).collect(Collectors.toList());
ints.forEach((i)-> System.out.print(ints.get(i-1)+ " "));

out put:

1 2 3 4 5

my question is why i must be i-1 inside the get method? does i-1 prevent the out of boundary issue?

Does below code acts like the for loop iteration?

(i)-> System.out.print(ints.get(i-1))

so is above code equal to this

for(Ineger i:ints)
   System.out.print(ints.get(i));
5
  • 2
    because list indexes are 0 based in Java. But +1 for asking a question about "Lambada's"! Commented Jun 25, 2014 at 2:23
  • I am right cuz it checks the boundary of the list in this way? Commented Jun 25, 2014 at 2:25
  • value of i is each member of the list Commented Jun 25, 2014 at 2:29
  • 1
    @KickButtowski: Your last code snippet would have the same problem: You need to do ints.get(i-1) to get that to work as well. Commented Jun 25, 2014 at 2:48
  • possible duplicate of For Loop with Lambda Expression in JAVA Commented Jul 28, 2015 at 12:19

3 Answers 3

16

The lambda parameter i takes the value of the items in the collection, not the indexes. You are subtracting 1 because the values happen to be one greater than their index.

If you tried with

List<Integer> ints = Stream.of(10,20,40,30,50).collect(Collectors.toList());
ints.forEach((i)-> System.out.print(ints.get(i-1)+ " "));

You would find the code does not work so well.

You should be able to simply do (not needing to do a get call)

ints.forEach((i)-> System.out.print(i + " "));

Your lambda and your proposed for loop are not equivalent.

ints.forEach((i)-> System.out.print(ints.get(i-1)))

Would be equivalent to

for(Integer i:ints)
   System.out.print(ints.get(i-1));

Note the preservation of the minus 1.


In response to the comment:

Lambdas are not loops, they are functions (effectively anyway). In your first example the forEach method is what provides the looping functionality. The argument lambda is what it should do on each iteration. This is equivalent to the body of your for loop

In the example in the comment, max is the function that provides the loop like behavior. It will iterate (do a loop) of the items to find the maximum value). The lambda you provide i -> i would be an identity function. It takes one parameter and returns that object unmodified.

Suppose you had a more complex object and you wanted to compare them on a particular member such as GetHighScore(). Then you could use i -> i.GetHighScore() to get the object with the highest score.

Sign up to request clarification or add additional context in comments.

6 Comments

@KickButtowski I edited the answer in response to your comment about the max function. I see while I was writing it comment was removed. Not sure if the content is helpful to you or not.
so function like max or min provide implicit iteration?
i read your comment and i found that function like max, min , or .... provide implicit iteration?
About min/max, exactly; implicit iteration. I am not sure whether there are exception to that rule for certain types. For example in .NET you can do Min against certain types and it will be converted to a SQL query rather than a loop. Not sure if Java has equivalents (yet). For something like a List then yes it would always be a full iteration for min/max
min and max do an internal iteration for unsorted streams, or multiple partial iterations for parallel streams, however, for streams that are already sorted in respect to the same order it may simply return the first resp. last element of the stream.
|
2

List indexes in Java are 0-based.

Therefore:

ints.get(0) == 1;
ints.get(1) == 2;
ints.get(2) == 3;
//etc...

You're calling ints.get(i-1) for each "i" where "i" is equal to the value of each element in the list "ints".

If you were to call ints.get(i) you'd be fetching elements with indices equal to 1,2,3,4 and 5 and 5 wouldn't be a valid index into a list with 5 elements.


This code:

ints.forEach((i)-> System.out.print(ints.get(i-1)+ " "));

is equivalent to:

for(int i : ints ) {
    System.out.print(ints.get(i-1) + " ");
}

Your examples aren't equivalent.

3 Comments

thank you for your answer but could you please answer the second part of my question too?
i know foreach acts like the for loop but my question is whether (i)-> System.out.print(ints.get(i-1)) is acting like for loop cuz in this code Integer maxInt = ints.stream() .max(Comparator.comparing(i -> i)) .get(); does i->i acts like the for loop? cuz as you see there is no foreach in the line.
to clarify my comment to your question, I like the typo that means you used the word for a sexy Latin dance "Lambada", instead of the greek character "Lambda"
-1

This is a wish, rather than a solution! Other language like NodeJS/JavaScript have a similar loop that passes two arguments to the lambda. Parameter i is the index and parameter j is the item from the container (regarless of container type).

ints.forEach((i,j)-> System.out.print("Index is ${i} and item is ${j}", i, j));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.