2016-07-07 3 views
-1

Я хочу использовать итератор guava или java8 foreach (может быть лямбда-выражение), вложенный в цикл, и обрабатывать некоторые операторы и возвращать длинную переменную. Вот мой код в родной Java. Извините, мой код может оказаться неэффективным. Я читаю через чистый доступ к не последним переменным внутри нового java 8 foreach, не представляется возможным.Гуава-итераторы для вложенных foreach

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; 

Я попытался, но не смог вернуть значения. Заранее благодарим за помощь!

+0

Значит, уровни просто отслеживают количество раз в цикле? –

+0

И попробуйте что-то вроде x + = getSomeValue (x) //, но должно ли оно быть getSomeValue (первым)? –

ответ

3

пару вещей:

  1. Прежде чем приступить к «рефакторинг», как тот, который вы спрашиваете, я действительно сильно рекомендую узнать больше «чистый» Java (который я предполагаю, что это дело здесь, @javalearner). Например, вы можете использовать long литералов вместо того, чтобы вручную бокс значения:

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

    Во всяком случае ...

  2. используя Guava здесь не поможет - это императив способ сделать это, и с Java 7 + Гуава вам придется писать неудобные анонимные классы (т.е. Function s), которые без поддержки языка болезненны. Который подводит меня к ...
  3. Java 8 и потоки. Вероятно, это лучший способ, но сначала вы должны исправить (?) Свой код и определить фактическую проблему - например, это заявление x= x + getSomeValue(x); оценивает x каждый раз и не учитывает FirstLevel (то же самое верно для y и SecondLevel) , поэтому я предполагаю, что вы на самом деле имели в виду x =+ getSomeValue(firstLevel);.

Имея все, что сказал, будьте более конкретными, какова ваша проблема на самом деле.

EDIT:

После вашего разъяснения, с помощью потоков кода может выглядеть следующим образом:

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

или с какой-то вспомогательный метод:

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(); 
} 
+0

Извините. Я был неправ. Ваш третий пункт правильный. Я сейчас редактировал. Если это невозможно в guava, возможно ли это в java 8 forEach, как выражения lamda? По крайней мере, мне нужно избегать встроенного синтаксиса forloop. Спасибо за ваш ответ. Большое спасибо – javalearner

+0

Я думал, что использование java8 будет эффективным и выглядит хорошо. Есть ли другой путь? – javalearner

+0

@javalearner Я добавил версию потоков. – Xaerxess

1

Прежде всего, не имеет смысла использовать вложенные значения Long и даже если вам понадобится значение в штучной упаковке, вам не нужно вызывать Long.valueOf, Java уже делает это для вас при преобразовании примитива long в коробку Long.

Далее, так как добавление long значения не зависит от порядка слагаемых, нет никаких причин, чтобы поддерживать две переменные в течение всей операции, когда вы будете добавлять их в конце все равно:

long result=0; 
for(FirstLevel first: Levels) { 
    result += getSomeValue(first); 
    for(SecondLevel second: first.getSecondLevels()) { 
     result += getSomeValue(second); 
    } 
} 
return result; 

Заметим, что оператор += делает то же самое, что и result = result + …, но избегает повторения целевого операнда.

Предполагая, что оба Levels и результат getSecondLevels, являются коллекции вы можете написать такой же, как операции потока, как

return Levels.stream() 
    .mapToLong(first -> 
     getSomeValue(first) + first.getSecondLevels().stream() 
      .mapToLong(second -> getSomeValue(second)).sum()) 
    .sum(); 

или, в качестве альтернативы

return Levels.stream() 
    .flatMapToLong(first -> LongStream.concat(
     LongStream.of(getSomeValue(first)), 
     first.getSecondLevels().stream().mapToLong(second -> getSomeValue(second)))) 
    .sum(); 

Если Levels является массивом, то вы должны заменить Levels.stream() на Arrays.stream(Levels), а также, если getSecondLevels() возвращает массив, вы должны заменить first.getSecondLevels().stream() на Arrays.stream(first.getSecondLevels())

+0

Приятный трюк с 'LongStream # concat' и' Stream # flatMapToLong'! – Xaerxess

+0

@Xaerxess: да, подход «flatMap» может стать важным для терминальных операций, а не как тривиальным, как суммирование. – Holger

Смежные вопросы