如何将Stream操作参数添加到我的函数中?

ski*_*iou 2 methods java-8 java-stream

我有一个函数在a上执行一些流操作(特别是一个过滤器)List.

public List<String> getAndFilterNames(List<Person> people, Predicate<Person> nameFilter){
  List<String> allNames = people.stream()
    .map(person -> person.getName())
    .filter(nameFilter)
    .collect(Collectors.toList());
  return allNames;
}
Run Code Online (Sandbox Code Playgroud)

我希望能够通过中间流操作(filter,distinct等),并有我的功能运行的终端操作之前执行该操作.就像是:

public List<String> getAndProcessNames(List<Person> people, <intermediate stream operation>){
  List<String> allNames = people.stream()
    .map(person -> person.getName())
    // perform <intermediate stream operation> here
    .collect(Collectors.toList());
  return allNames;
}
Run Code Online (Sandbox Code Playgroud)

虽然,根据我目前的经验水平,似乎是不可能的.一些中间操作有一个参数(比如filter),有些没有(比如distinct),所以我不能设置一个能处理所有情况的参数类型...我想我可以创建一些签名,但是FunctionSupplier.

即便如此,该功能界面与参数的功能需要变化...... filter需要Predicate,map需要Function,并从我的理解,是没有办法来表示一个通用的功能接口.那是对的吗?它们都没有真正的公共类或接口.

那么,到底,看来我最好的选择是公正mapcollect,然后运行所需的我流操作的情况下,逐案的基础,如:

public List<String> getNames(List<Person> people){
  List<String> allNames = people.stream()
    .map(person -> person.getName())
    .collect(Collectors.toList());
  return allNames;
}

List<Person> employees = // a bunch of people
List<String> employeeNames = getNames(employees);
employeeNames = employeeNames.stream(). // desired operations
Run Code Online (Sandbox Code Playgroud)

编辑:或者,@ perHolger:

public Stream<String> getNamesStream(List<Person> people){
  Stream<String> namesStream = people.stream()
    .map(person -> person.getName());
  return namesStream;
}

List<Person> employees = // a bunch of people
Stream<String> employeeNamesStream = getNamesStream(employees);
employeeNamesStream(). // desired operations
Run Code Online (Sandbox Code Playgroud)

还是有什么我想念的?

Bri*_*etz 11

你需要的是从功能StreamStream.例如:

public List<String> processNames(Function<Stream<String>, Stream<String>> f) {
    return f.apply(people.stream().map(Person::getName))
            .collect(toList());
}
Run Code Online (Sandbox Code Playgroud)

然后调用如下:

List<String> filteredNames = processNames(s -> s.filter(n -> n.startsWith("A")));
Run Code Online (Sandbox Code Playgroud)

  • OP想知道是否有任何方法可以将"流操作"作为数据传递."通过一元运算符代替"的成语起初并不明显,有时也很有用.在这种情况下是否值得是无关紧要的(并且对于这是否适合它的适当场所的挑剔似乎故意忽略了这一点).这里的要点是,从"传递流操作"到"传递一种修改流的方式"的请求有一个合理的高级,这是一个在工具箱中有用的工具,而且显然还没有发生过OP(和其他人). (3认同)
  • 那么,唯一的"优势"是调用者被迫接收收集的`List`,而不是被允许链接自己的终端操作.并且该函数不允许映射到"String"以外的其他内容.我称之为反模式,由以集合为中心的视图引起.应该提到替代方案,只需返回流以允许任意后续操作. (2认同)
  • @BrianGoetz这很棒; 谢谢.即使我知道如何对`Function <Stream <String>,Stream <String >>进行分类,我也不知道我会从那里做什么.肯定会添加到我的工具箱中. (2认同)
  • @Holger我看到你来自哪里,虽然我的函数的契约是总是返回一个`List <String>`.我没有想到返回流本身的想法; 我发现它可能对将来的其他东西有用. (2认同)