Как избежать последней новой строки при записи в файл с использованием Stream API и Printwriter? - PullRequest
0 голосов
/ 08 ноября 2018

Я изучаю Lambdas и Stream API, который поставляется с Java 8. Я хотел создать что-то вроде этого, используя Stream API только для учебных целей:

b
bb
bbb
bbbb
bbbbb
bbbb
bbb
bb
b

и вот реализация, которую я придумал:

final File file = new File("/Users/kt/sample.data");
final PrintWriter printWriter = new PrintWriter(file);

Stream.concat(IntStream.iterate(1, i -> i + 1).limit(6).boxed(), 
              IntStream.iterate(5, i -> i - 1).limit(5).boxed())
      .map(counter -> {
          StringBuilder stringBuilder = new StringBuilder();
          IntStream.range(1, counter).forEach(c -> stringBuilder.append("b"));
          return stringBuilder.toString();
      }).filter(s -> s.length() != 0).forEach(s -> printWriter.println(s));

printWriter.flush();
printWriter.close();

Теперь единственная проблема в том, что в итоге я получаю пустую последнюю строку в файле, поскольку printwriter печатает последнюю букву 'b' вместе с новой строкой.

Очевидно, что я могу передать 4 вместо 5 во 2-й IntStream.iterate У меня есть, и перед сбросом printWriter я могу сделать: printWriter.print("b");, но моя цель - использовать Stream API.

Как мне добиться этого больше Streamy ?

Ответы [ 3 ]

0 голосов
/ 08 ноября 2018

Не знаю точно, что означает Streamy, но как насчет этого:

    int[] arr = new int[max * 2 - 1];
    arr[(max * 2) / 2] = max;

    IntStream.range(0, max)
             .forEachOrdered(x -> {
                 arr[x] = x + 1;
                 arr[x + max - 1] = max - x;
             });

    String result = Arrays.stream(arr)
                          .mapToObj(x -> IntStream.range(0, x)
                                                  .mapToObj(i -> "b")
                                                  .collect(Collectors.joining()))
                          .collect(Collectors.joining("\n"));
0 голосов
/ 08 ноября 2018

Вы можете сделать свою работу намного проще, чем

Files.write(Paths.get("/Users/kt/sample.data"),
    () -> IntStream.range(1, 10)
        .<CharSequence>mapToObj(i -> "bbbbb".substring(Math.abs(5-i)))
        .iterator());

Не говоря уже о

Files.write(Paths.get("C:\\Users\\pietsch\\AppData\\Local\\Temp\\output"),
    Collections.singletonList("b\nbb\nbbb\nbbbb\nbbbbb\nbbbb\nbbb\nbb\nb"));

Если из-за жестко закодированных инвариантов это слишком похоже на читерство, измените код, чтобы разрешить указание произвольного максимального размера строки:

int size = 5;

int[] codepoints = IntStream.range(0, size).map(i -> 'b').toArray();
Files.write(Paths.get("/Users/kt/sample.data"),
    () -> IntStream.range(1, size*2)
        .<CharSequence>mapToObj(i -> new String(codepoints, 0, size-Math.abs(size-i)))
        .iterator());
0 голосов
/ 08 ноября 2018

Я рекомендую использовать переменную для хранения размера, так как есть несколько мест, где это требуется: maxSize


  1. Вы можете объединить свои элементы с помощью обратной строки, а затем print, и в качестве подсказки вы можете упростить использование StringBuilder с операцией map
int maxSize = 5;
String str =
        IntStream.concat(IntStream.iterate(2, i -> i + 1).limit(maxSize),
                         IntStream.iterate(maxSize, i -> i - 1).limit(maxSize - 1))
                 .mapToObj(count -> IntStream.range(1, count).mapToObj(c -> "b").collect(Collectors.joining()))
                 .collect(Collectors.joining("\n"));

printWriter.print(str);
  1. Второй вариант, чтобы избежать переменной String, заключался в добавлении \n между каждым блоком, затем ограничении для удаления последнего и печати всех, но это не более эффективно для обоих:
int maxSize = 5;
IntStream.concat(IntStream.iterate(2, i -> i + 1).limit(maxSize),
                 IntStream.iterate(maxSize, i -> i - 1).limit(maxSize - 1))
         .mapToObj(count -> IntStream.range(1, count).mapToObj(c -> "b").collect(Collectors.joining()))
         .flatMap(b -> Stream.of(b, "\n"))
         .limit((maxSize * 2 - 1) * 2 - 1)
         .forEach(printWriter::print);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...