在Java中对单个流的元素执行多个不相关的操作 [英] Perform multiple unrelated operations on elements of a single stream in Java

查看:57
本文介绍了在Java中对单个流的元素执行多个不相关的操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何对单个流的元素执行多个不相关的操作?

How can I perform multiple unrelated operations on elements of a single stream?

假设我有列表< String> 由文本组成。列表中的每个字符串可能包含也可能不包含某个单词,表示要执行的操作。让我们说:

Say I have a List<String> composed from a text. Each string in the list may or may not contain a certain word, which represents an action to perform. Let's say that:


  • 如果字符串包含'of',则该字符串中的所有单词都必须计算

  • 如果字符串包含'for',则必须返回第一次出现'for'之后的部分,产生带有所有子字符串的 List< String>

  • if the string contains 'of', all the words in that string must be counted
  • if the string contains 'for', the portion after the first occurrence of 'for' must be returned, yielding a List<String> with all substrings

当然,我可以这样做:

List<String> strs = ...;

List<Integer> wordsInStr = strs.stream()
    .filter(t -> t.contains("of"))
    .map(t -> t.split(" ").length)
    .collect(Collectors.toList());

List<String> linePortionAfterFor = strs.stream()
    .filter(t -> t.contains("for"))
    .map(t -> t.substring(t.indexOf("for")))
    .collect(Collectors.toList());

然后列表将被遍历两次,如果<$ c $,可能会导致性能下降c> strs 包含大量元素。

but then the list would be traversed twice, which could result in a performance penalty if strs contained lots of elements.

是否有可能以某种方式执行这两个操作而不在列表上遍历两次?

Is it possible to somehow execute those two operations without traversing twice over the list?

推荐答案

如果你想要一次传递 Stream 那么你必须使用自定义收集器(可能并行化)。

If you want a single pass Stream then you have to use a custom Collector (parallelization possible).

class Splitter {
  public List<String> words = new ArrayList<>();
  public List<Integer> counts = new ArrayList<>();

  public void accept(String s) {
    if(s.contains("of")) {
      counts.add(s.split(" ").length);
    } else if(s.contains("for")) {
      words.add(s.substring(s.indexOf("for")));
    }
  }

  public Splitter merge(Splitter other) {
    words.addAll(other.words);
    counts.addAll(other.counts);
    return this;
  }
}
Splitter collect = strs.stream().collect(
  Collector.of(Splitter::new, Splitter::accept, Splitter::merge)
);
System.out.println(collect.counts);
System.out.println(collect.words);

这篇关于在Java中对单个流的元素执行多个不相关的操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆