使用Java 8流时,采用列表,从中创建流,执行业务并将其转换回来是很常见的。类似的东西:
Stream.of(-2,1,2,-5)
.filter(n -> n > 0)
.map(n -> n * n)
.collect(Collectors.toList());
为什么“.collect(Collectors.toList())
”部分没有捷径/方便的方法?在Stream界面上,有一种方法可以将结果转换为名为toArray()
的数组,为什么缺少toList()
?
恕我直言,将结果转换为列表比使用数组更常见。我可以忍受这种说法,但称这种丑陋是令人讨厌的。
有什么想法吗?
答案 0 :(得分:5)
至于“为什么”,我相信评论中有很多论据。但是,我同意你的意见,因为没有toList()
方法会很烦人。使用toIterable()
方法也是如此。
所以我会向你展示一个技巧,让你无论如何都可以使用这两种方法。幸运的是,Java非常灵活,可以让你做各种有趣的事情。大约10年前,我读了this article,它描述了一种将方法“插入”到任何给定接口的诙谐技巧。诀窍在于使用代理来调整没有所需方法的接口。多年来,我发现它具有所有适配器模式的优点,而它缺乏所有的缺点。这就是我所说的大事。
这是一个示例代码,只是为了表明这个想法:
public class Streams {
public interface EnhancedStream<T>
extends Stream<T> {
List<T> toList();
Iterable<T> toIterable();
}
@SuppressWarnings("unchecked")
public static <T> EnhancedStream<T> enhance(Stream<T> stream) {
return (EnhancedStream<T>) Proxy.newProxyInstance(
EnhancedStream.class.getClassLoader(),
new Class<?>[] {EnhancedStream.class},
(proxy, method, args) -> {
if ("toList".equals(method.getName())) {
return stream.collect(Collectors.toList());
} else if ("toIterable".equals(method.getName())) {
return (Iterable<T>) stream::iterator;
} else {
// invoke method on the actual stream
return method.invoke(stream, args);
}
});
}
public static void main(String[] args) {
Stream<Integer> stream1 = Stream.of(-2, 1, 2, -5).
filter(n -> n > 0).map(n -> n * n);
List<Integer> list = Streams.enhance(stream1).toList();
System.out.println(list); // [1, 4]
Stream<Integer> stream2 = Stream.of(-2, 1, 2, -5).
filter(n -> n > 0).map(n -> n * n);
Iterable<Integer> iterable = Streams.enhance(stream2).toIterable();
iterable.forEach(System.out::println); // 1
// 4
}
}
我们的想法是使用EnhancedStream
接口,通过定义要添加的方法来扩展Java的Stream
接口。然后,动态代理通过将原始Stream
方法委托给正在调整的实际流来实现此扩展接口,而它只是为新方法(未在Stream
中定义的方法)提供内联实现。 / p>
此代理可通过静态方法获得,该方法可透明地执行所有代理操作。
请注意,我并未声明这是最终解决方案。相反,它只是一个可以高度改进的示例,即对于返回另一个Stream
的{{1}}的每个方法,您也可以返回该代理。这将允许Stream
被链接(您需要在EnhancedStream
接口中重新定义这些方法,以便它们返回EnhancedStream
协变返回类型)。此外,缺少适当的异常处理,以及更强大的代码来决定是否将方法的执行委托给原始流。
答案 1 :(得分:4)
Java 16 引入了 Stream.toList():
Stream.of(-2,1,2,-5)
.filter(n -> n > 0)
.map(n -> n * n)
.toList();
新方法与现有的 collect(toList())
略有不同:它返回一个不可修改的列表。
答案 2 :(得分:1)
这是一个简单的帮助程序类,可以使这更容易:
public class Li {
public static <T> List<T> st(final Stream<T> stream) {
return stream.collect(Collectors.toList());
}
}
使用示例:
List<String> lowered = Li.st(Stream.of("HELLO", "WORLD").map(String::toLowerCase));