代码之家  ›  专栏  ›  技术社区  ›  Koray Tugay

在使用streamapi和Printwriter写入文件时,如何避免中的最后一行?

  •  3
  • Koray Tugay  · 技术社区  · 6 年前

    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 到第二个 IntStream.iterate 我已经洗过了 printWriter printWriter.print("b"); ,但我的目标是利用流API。

    我怎样才能做到这一点呢 流线型 ?

    3 回复  |  直到 6 年前
        1
  •  2
  •   azro    6 年前

    我建议使用变量来存储大小,因为有几个地方需要它: 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);
    
        2
  •  7
  •   Holger    6 年前

    你可以把工作做得简单得多

    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());
    
        3
  •  1
  •   Eugene    6 年前

        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"));