如何调用参数化 getter 作为 java 8 流中的映射器?
How to call a parametrized getter as a mapper in a java 8 stream?
用例
我目前在很多适配器中都有这种模式:
entries.stream()
.filter(Entry.class::isInstance)
.map(Entry.class::cast)
.map(Entry::getFooBar)
.collect(Collectors.toList());
其中条目是 List
实现特定接口的对象。不幸的是,这个接口——它是第 3 方库的一部分——没有定义通用的 getters。要创建我想要的对象列表,我需要搜索它们、转换它们并调用适当的 getter 方法。
我打算将它重构为一个助手 class 这样的:
public static <T, O> List<O> entriesToBeans(List<T> entries,
Class<T> entryClass, Supplier<O> supplier) {
return entries.stream()
.filter(entryClass::isInstance)
.map(entryClass::cast)
.map(supplier) // <- This line is invalid
.collect(Collectors.toList());
}
然后我会调用此方法进行转换:
Helper.entriesToBeans(entries,
Entry_7Bean.class,
Entry_7Bean::getFooBar);
不幸的是,我无法将 getter 传递给重构函数并让地图调用它,因为 map
需要一个函数。
问题
- 重构后的getter如何调用?
方法如:
class T {
public O get() { return new O(); }
}
将映射到 Function<T, O>
。
因此您只需将方法签名更改为:
public static <T, O> List<O> entriesToBeans(List<T> entries,
Class<T> entryClass, Function<T, O> converter) {
更新:强制转换的原因,我怀疑是你的原始列表可能包含不是Ts的元素。所以你也可以将签名更改为:
public static <T, O> List<O> entriesToBeans(List<?> entries,
Class<T> entryClass, Function<T, O> converter) {
然后您可以传递一个 List<Object>
,例如,只保留列表中的 T,转换和转换。
作为参考,这是一个工作示例(打印 John, Fred
):
static class Person {
private final String name;
Person(String name) { this.name = name; }
String name() { return name; }
}
public static void main(String[] args) {
List<String> result = entriesToBeans(Arrays.asList(new Person("John"), new Person("Fred")),
Person.class, Person::name);
System.out.println("result = " + result);
}
public static <T, O> List<O> entriesToBeans(List<?> entries,
Class<T> entryClass, Function<T, O> converter) {
return entries.stream()
.filter(entryClass::isInstance)
.map(entryClass::cast)
.map(converter)
.collect(Collectors.toList());
}
您应该传递一个 Function<T, O>
而不是:
public static <T, O> List<O> entriesToBeans(List<T> entries, Class<T> entryClass,
Function<T, O> mapper) {
return entries.stream().filter(entryClass::isInstance)
.map(entryClass::cast).map(mapper)
.collect(Collectors.toList());
}
用例
我目前在很多适配器中都有这种模式:
entries.stream()
.filter(Entry.class::isInstance)
.map(Entry.class::cast)
.map(Entry::getFooBar)
.collect(Collectors.toList());
其中条目是 List
实现特定接口的对象。不幸的是,这个接口——它是第 3 方库的一部分——没有定义通用的 getters。要创建我想要的对象列表,我需要搜索它们、转换它们并调用适当的 getter 方法。
我打算将它重构为一个助手 class 这样的:
public static <T, O> List<O> entriesToBeans(List<T> entries,
Class<T> entryClass, Supplier<O> supplier) {
return entries.stream()
.filter(entryClass::isInstance)
.map(entryClass::cast)
.map(supplier) // <- This line is invalid
.collect(Collectors.toList());
}
然后我会调用此方法进行转换:
Helper.entriesToBeans(entries,
Entry_7Bean.class,
Entry_7Bean::getFooBar);
不幸的是,我无法将 getter 传递给重构函数并让地图调用它,因为 map
需要一个函数。
问题
- 重构后的getter如何调用?
方法如:
class T {
public O get() { return new O(); }
}
将映射到 Function<T, O>
。
因此您只需将方法签名更改为:
public static <T, O> List<O> entriesToBeans(List<T> entries,
Class<T> entryClass, Function<T, O> converter) {
更新:强制转换的原因,我怀疑是你的原始列表可能包含不是Ts的元素。所以你也可以将签名更改为:
public static <T, O> List<O> entriesToBeans(List<?> entries,
Class<T> entryClass, Function<T, O> converter) {
然后您可以传递一个 List<Object>
,例如,只保留列表中的 T,转换和转换。
作为参考,这是一个工作示例(打印 John, Fred
):
static class Person {
private final String name;
Person(String name) { this.name = name; }
String name() { return name; }
}
public static void main(String[] args) {
List<String> result = entriesToBeans(Arrays.asList(new Person("John"), new Person("Fred")),
Person.class, Person::name);
System.out.println("result = " + result);
}
public static <T, O> List<O> entriesToBeans(List<?> entries,
Class<T> entryClass, Function<T, O> converter) {
return entries.stream()
.filter(entryClass::isInstance)
.map(entryClass::cast)
.map(converter)
.collect(Collectors.toList());
}
您应该传递一个 Function<T, O>
而不是:
public static <T, O> List<O> entriesToBeans(List<T> entries, Class<T> entryClass,
Function<T, O> mapper) {
return entries.stream().filter(entryClass::isInstance)
.map(entryClass::cast).map(mapper)
.collect(Collectors.toList());
}