2016-04-13 3 views
0

У меня есть вложенный цикл цикла, который я бы хотел заменить потоками, но я не могу понять, как это сделать, если это возможно. Основной цикл нижеJava-потоки заменяют вложенные для цикла

for (Object outer : owner.getOuterList()) 
    for (Object inner : owner.getInnerList()) 
     if (cond(outer, inner)) 
      func(outer, inner); 
     else 
      moo(outer, inner); 

Единственное решение, которое я был в состоянии прибыть в основном это выглядит точно так же, используя forEach вместо петель. flatMap кажется применимым, но я не могу понять, как получить оба списка.

+0

Если это чисто императивные вещи, то да, это будет выглядеть точно так же. Потоки предназначены для преобразования и фильтрации и выведения _new_ элементов, как правило. –

+1

Да, ссылка @Pillar в основном то, что вам нужно. '.flatMap (внешний -> owner.getInnerList(). stream(). map (inner -> new Object [] {внешний, внутренний)))' В проблеме всегда есть класс Tuple для хранения как 'inner', так и' outer'. Здесь, так как они оба являются «Object», мы могли бы злоупотреблять массивом ... В целом: сохраняйте цикл 'for'. – Tunaki

+0

Хорошо, спасибо Столп и Тунаки. Вид отстой, что нет более чистого способа написать его. – twentylemon

ответ

1

Основная проблема заключается в том, что тело внутреннего цикла

if (cond(outer, inner)) 
    func(outer, inner); 
else 
    moo(outer, inner); 

не имеет аналогов в потоке API и остается одной непрозрачной действия для большинства мыслимых решений, поэтому самое простое решение, чтобы выразить это в качестве Consumer, который вы вызываете с помощью вложенного forEach, который не дает преимущества для вложенного цикла for, который у вас уже есть.

Если вы хотите обеспечить решение flatMap на основе, вы можете сделать следующее:

owner.getOuterList().stream().flatMap(
    outer -> owner.getInnerList().stream().<Runnable>map(
     inner -> cond(outer, inner)?() -> func(outer, inner):() -> moo(outer, inner)) 
).forEach(Runnable::run); 

Он не нужен типа пара/кортеж для отображения на [outer,inner] как функции способен сам себе захватывать эти значения. Обратите внимание, что это будет оценивать условие во внутренней обработке потока, но фактический вызов либо func, либо moo произойдет во внешней обработке потока. Вы можете применять обработки все в пределах внешнего потока с

owner.getOuterList().stream().flatMap(
    outer -> owner.getInnerList().stream().<Runnable>map(
     inner ->() -> { if(cond(outer,inner)) func(outer,inner); else moo(outer,inner); }) 
).forEach(Runnable::run); 

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

Я думаю, ясно, что ни одна из них не является реальной победой над исходной вложенной петлей for.

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