java 将第一个元素从同一个Stream添加到Stream

14ifxucb  于 2023-01-07  发布在  Java
关注(0)|答案(1)|浏览(132)

我有一个JsonNode流,我想把它转换成类似CSV的Stream〈String[]〉,其中第一行是头,然后是值。TextDataUtils.sample也有同样的期望。我目前使用Stream.concat来实现这一点,但第一行总是[],因为我只在开始处理值流后才提取头。

GoogleAdsGetValuesResponse getValuesResponse = client.getValues(getValuesRequest);
    AtomicLong consumedRows = new AtomicLong();
    List<String> headers = new ArrayList<>();
    Stream<String[]> valueStream =
        getValuesResponse
            .getValuesStream()
            .limit(request.getLimit())
            .map(
                rowNode -> {
                  if (consumedRows.get() == 0) {
                    extractAllKeys(rowNode, "", headers);
                    headers.removeIf(header -> !header.contains("."));
                  }
                  String[] row =
                      headers.stream()
                          .map(header -> rowNode.at(getJsonPointerString(header)).asText())
                          .toArray(String[]::new);
                  consumedRows.getAndIncrement();
                  return row;
                });

    Stream<String[]> headerStream = Stream.of(headers.toArray(String[]::new), new String[] {});
    Stream<String[]> dataStream = Stream.concat(headerStream, valueStream);
    return TextDataUtils.sample(dataStream, Collections.emptyMap(), request.getLimit(), false);

我如何实现这个目标?从同一个流中添加第一个元素到流中。感谢您的任何建议。我真的很感谢您能提供的任何帮助。

7tofc5zh

7tofc5zh1#

Java不允许您在迭代集合时更改集合,因此您想做的事情是不可能的。
我建议首先用limit(1)处理头,然后继续用skip(1)将其与剩余的已处理项连接起来。
大致如下:

Stream<String> headerStream = newResponseStream.limit(1).getHeaders()
Stream<String[]> valueStream = newResponseStream.skip(1).getRows()

Stream<String[]> dataStream = Stream.concat(headerStream, valueStream);
return TextDataUtils.sample(dataStream, Collections.emptyMap(), request.getLimit(), false);

请注意,您不能重用启动响应流。如果底层流是正确的延迟获取,这仍然是有效的。
顺便说一句,我会避免编写有副作用的map函数。这会使代码更难推理。

相关问题