我如何制作Stream的副本,以便在使用时我使用Java 8中的副本?

时间:2016-07-27 11:57:35

标签: java java-8 java-stream

这是我的代码的外观:

public static String firstContainsChars(Stream<String> items,String charset) {
    char[] inChars = charset.toCharArray();
    for (char ch:inChars) {
        items.filter(s->s.contains(String.valueOf(ch)));
    }
    return items.findFirst().orElse("No Match Found");
}

事实上,我收集了一个字符集Stringfilter,但问题是我无法在foreach中多次使用该流循环和编译器说:

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed

有关如何复制Stream的任何想法,而不需要将其作为Collection收集,因为这将是完全浪费。 (在chnage之后流式传输和收集)?

3 个答案:

答案 0 :(得分:3)

正如我在评论部分中所说,您必须将items分配给循环中的新管道。

public static String firstContainsChars(Stream<String> items, String charset) {
  char[] inChars = charset.toCharArray();
  for (char ch : inChars) {
    items = items.filter(s -> s.contains(String.valueOf(ch)));
  }
  return items.findFirst().orElse("No Match Found");
}

但更简洁的方法是Stream你的字符集,例如:

public static String firstContainsChars(Stream<String> items, String charset) {
  return items.filter(s -> charset.codePoints().allMatch(cp -> s.indexOf(cp) != -1))
              .findFirst().orElse("No Match Found");
}

答案 1 :(得分:1)

您实际上不需要复制流,只需在过滤器中流式传输字符集:

public static String firstContainsChars(Stream<String> items, String charset){

    return items
            .filter(s-> charset
                        .chars() // stream of all the chars in charset
                        .mapToObj(i -> (char)i ) //chars() is actually a stream of ints... convert to chars
                        .allMatch(c -> s.indexOf(c) >= 0) //check that all chars are contained in the string
            )
            .findFirst()
            .orElse("No Match Found");
}

List<String> items = Arrays.asList("foo", "bar", "foobar");

String s1 = firstContainsChars(items.stream(), "of");  // -> "foo"
String s2 = firstContainsChars(items.stream(), "rab"); // -> "bar"
String s3 = firstContainsChars(items.stream(), "fob"); // -> "foobar"
String s4 = firstContainsChars(items.stream(), "xyz"); // -> "No Match Found"

答案 2 :(得分:0)

我不会进入你努力的目标,但是说你的代码什么都不做,因为filter只是流上的中间操作,它不像findFirst那样终止操作。
现在,您可以重写代码以查看其工作方式:

public static String firstContainsChars(Stream<String> items,String charset) {
    String result = "";
    char[] inChars = charset.toCharArray();
    for (char ch:inChars) {
      result = items.filter(s->s.contains(String.valueOf(ch))).findFirst().orElse("No Match Found");
      System.out.println(result);
    }
    return result;
}

但请阅读文档,以了解其https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps

的流和生命周期的操作