Как отобразить несколько элементов в потоках Java 8? - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть класс

public class Step
      {
         boolean isActive;
         String name;
      }

У меня есть Коллекция типа Шаги.Без использования потоков это то, что у меня сейчас

  StringBuilder stringBuilder = new StringBuilder();
  for (Step step : steps)
  {
     List<String> nextStepNames = getNextStepNames(step);
     List<String> conditions = getConditions(step);
     for (int i = 0; i < nextStepNames.size(); i++)
     {
        stringBuilder.append("If ").append(step.getName()).append("is active, and condition (").append(conditions.get(i)).append(") is true, then move to ").append(nextStepNames.get(i)).append("\n");
     }
  }

Если моя коллекция шагов содержит stepA, StepB и stepC, то это мой вывод:

If stepA is active, and condition (c1A) is true, then move to step1A
If stepA is active, and condition (c2A) is true, then move to step2A
If stepA is active, and condition (c3A) is true, then move to step3A
If stepB is active, and condition (c1B) is true, then move to step1B
If stepB is active, and condition (c2B) is true, then move to step2B
If stepB is active, and condition (c3B) is true, then move to step3B
If stepC is active, and condition (c1C) is true, then move to step1C
If stepC is active, and condition (c2C) is true, then move to step2C
If stepC is active, and condition (c3C) is true, then move to step3C

nextStepNames и conditions списки имеют одинаковый размер, а индексы в списках соответствуют друг другу.

Мне не удалось преобразовать этот код в потоки.Я не уверен, если это возможно.

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

Попробуйте это:

String output = Arrays.stream(steps) // if it's an array or steps.stream() for a list
    .flatMap(step -> IntStream.range(0, getNextStepNames(step).size())
        .mapToObj(i -> String.format(
            "If %s is active, and condition (%s) is true, then move to %s",
            step.getName(),
            getConditions(step).get(i),
            getNextStepNames(step).get(i))))
    .collect(Collectors.joining("\n"));

Наш начальный поток содержит только три элемента (шаг A, B и C), поэтому для каждого элемента нам нужен другой поток.Мы создаем IntStream со всеми действительными индексированными обоих списков.Мы отображаем их в строку, получая элементы из двух методов.Я использовал String.format, но это, конечно, можно заменить StringBuilder или простой конкатенацией строк.

На данный момент у нас есть потоки в потоках.Нам нужно свести его к одному потоку, просто вызвав flatMap.

Наконец, мы можем объединить все элементы, используя \n в качестве клея.


Жаль, что getNextStepNames и getConditions оба кажутся родственными, но все же раздельными.Но это другая история.

0 голосов
/ 27 февраля 2019

Java не обладает способностями эффективно решать проблему в элегантном, чисто функциональном стиле.

Однако вы можете попробовать что-то вроде

    str = steps.stream()
        .map(step ->
            IntStream
                .range(0, getNextStepNames(step).size())
                .mapToObj(i -> Stream.of(
                    "If ",
                    step.getName(),
                    " is active, and condition (",
                    getConditions(step).get(i),
                    ") is true, then move to ",
                    getNextStepNames(step).get(i),
                    "\n"))
                .flatMap(Function.identity())
        )
        .flatMap(Function.identity())
        .collect(Collectors.joining());

Это довольно неэффективно из-за повторной оценкиgetNextStepNames и getConditions и невозможность заранее выделить весь выходной буфер.

Конечно, вы можете попытаться уменьшить это, используя сторонние библиотеки, но imho, это не стоит усилий.

Ваше решение более эффективно и намного проще для понимания и обслуживания.Вы можете еще больше улучшить это, инициализируя StringBuilder размером, равным или немного большим, чем конечный размер вывода.

0 голосов
/ 25 февраля 2019

На шаг ближе к этому может быть:

for (Step step : steps) {
    List<String> nextStepNames = getNextStepNames(step);
    List<String> conditions = getConditions(step);
    IntStream.range(0, nextStepNames.size())
            .forEach(i -> stringBuilder.append("If ")
                    .append(step.getName())
                    .append("is active, and condition (")
                    .append(conditions.get(i))
                    .append(") is true, then move to ")
                    .append(nextStepNames.get(i)).append("\n"));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...