我有一个函数可以在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;
}
我希望能够传递中间流操作(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;
}
尽管如此,根据我目前的经验水平,这似乎是不可能的。某些中间操作具有参数(如filter
),而其他参数则不具有(distinct
),因此我无法设置单个参数类型来处理所有情况。 ..我想我可以使用Function
和Supplier
创建几个签名。
即使这样,带参数的函数所需的函数接口也会有所不同...... filter
需要Predicate
,map
需要Function
,而且根据我的理解,没有办法表示通用的功能接口。那是对的吗?它们都没有实际的公共类或接口。
所以,最后,似乎我最好的选择只是map
和collect
,然后根据具体情况运行我想要的流操作,如:
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
编辑:或者,根据@Holger:
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
或者我有什么遗失的东西?
答案 0 :(得分:11)
您想要的是从{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::*"
]
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::YOURBUCKETNAME",
"arn:aws:s3:::YOURBUCKETNAME/*"
]
}
]
}
到Stream
的功能。例如:
Stream
然后调用:
public List<String> processNames(Function<Stream<String>, Stream<String>> f) {
return f.apply(people.stream().map(Person::getName))
.collect(toList());
}
答案 1 :(得分:0)
是的,你是对的。中间操作没有扩展的公共基接口,但由于它们实际执行的操作不同,也不应该有。
你可以创建一些可以链接这些调用的方法:
private static <T> Stream<T> applyPredicates(Stream<T> input, List<Predicate<T>> predicates) {
Stream<T> result = Stream.concat(input, Stream.empty());
for (Predicate<T> pred : predicates) {
result = result.filter(pred);
}
return result;
}
/**
* this could be modified to accept more then one parameters
*/
private static <T, R> Stream<R> applyFunction(Stream<T> input, Function<T, R> function) {
return input.map(function);
}
然后例如:
List<String> list = Arrays.asList("one", "two", null, "three");
Predicate<String> p1 = t -> t != null;
Predicate<String> p2 = t -> t.startsWith("t");
applyFunction(applyPredicates(list.stream(), Arrays.asList(p1, p2)), String::length)
.collect(Collectors.toList());
请注意,必须重载applyFunctions以将多个函数作为输入参数,因为每个映射操作可能会将流从T更改为R然后更改为Y,依此类推。