javalearner javalearner - 4 months ago 27
Java Question

Guava iterators for nested foreach

I want to use guava iterator or java8 foreach(may be lambda expression) nested for loop and process some statements and return a long variable. Here is my code in native java. Please excuse my code may not efficient. I read over net accessing non final variables inside new java 8 foreach is not possible.

Long x = Long.valueOf(0);
Long y = Long.valueOf(0);
for(FirstLevel first : Levels)
{
if(first.getSecondLevels() == null)
{
x= x + getSomeValue(first);
}
for (SecondLevel second : first.getSecondLevels())
{
y = y + getSomeValue(second);
}
}
return x + y;


I have tried but unable to return the values. Thanks in advance for help!

Answer

Couple things:

  1. Before approaching "refactoring" like that one you ask, I really strongly recommend learning more "pure" Java (which I assume is the case here, @javalearner). For example you can use long literals instead of manually boxing values:

    long x = 0L;
    long y = 0L;
    

    Anyway...

  2. using Guava won't help here - this is the imperative way of doing it, and with Java 7 + Guava you'd have to write awkward anonymous classes (i.e. Functions), which without language support is painful. Which brings me to...
  3. Java 8 and Streams. This is probably the best way to go, but first you have to fix (?) your code and define actual problem - for example this statement x= x + getSomeValue(x); evaluates x each time and does not take FirstLevel into account (same is true for y and SecondLevel), so I assume what you really meant was x =+ getSomeValue(firstLevel);.

Having all that said - please be more specific what your problem really is.

EDIT:

After your clarification, using streams your code could look like this:

final long sum = levels.stream()
        .mapToLong(first -> getSomeValue(first) + first.getSecondLevels().stream().mapToLong(this::getSomeValue).sum())
        .sum();

or with some helper method:

final long s = levels.stream()
        .mapToLong(first -> getSomeValue(first) + getSecondLevelSum(first))
        .sum();

private long getSecondLevelSum(final FirstLevel first) {
    return first.getSecondLevels().stream().mapToLong(this::getSomeValue).sum();
}