如果不违反 Java 流框架的构建原则,这是不可能的。这将完全违反从物理表示中抽象流的想法。
批量数据操作的顺序进入一个管道,见下图:
流在某种程度上类似于Schrödinger's cat - 在您调用终端操作之前它不会实现。流处理是完全抽象的,与原始流源分离。
如果您想对原始数据存储进行如此低级别的工作,请不要因为简单地避开流而感到羞耻。它们只是一种工具,而不是任何神圣的东西。通过引入流,Good Old Collections 仍然和以前一样好,并增加了内部迭代的价值 - 新的 Iterable.forEach() 方法。
添加以满足您的好奇心:)
可能的解决方案如下。我自己不喜欢它,而且我无法解决那里的所有泛型问题,但它有局限性。
这个想法是创建一个收集器,它返回与输入集合相同的类型。然而,并不是所有的集合都提供了一个空构造函数(没有参数),没有它Class.newInstance() 方法就不起作用。还有 lambda 表达式中检查异常的尴尬问题。 (这里的这个不错的答案中提到了:https://stackoverflow.com/a/22919112/2886891)
public Collection<Integer> getBiggerThan(Collection<Integer> col, int value) {
// Collection below is an example of one of the rare appropriate
// uses of raw types. getClass returns the runtime type of col, and
// at runtime all type parameters have been erased.
@SuppressWarnings("rawtypes")
final Class<? extends Collection> clazz = col.getClass();
System.out.println("Input collection type: " + clazz);
final Supplier<Collection<Integer>> supplier = () -> {
try {
return clazz.newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(
"A checked exception caught inside lambda", e);
}
};
// After all the ugly preparatory code, enjoy the clean pipeline:
return col.stream()
.filter(v -> v > value)
.collect(supplier, Collection::add, Collection::addAll);
}
如您所见,它通常可以工作,假设您的原始集合提供了一个空构造函数。
public void test() {
final Collection<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
final Collection<Integer> arrayList = new ArrayList<>(numbers);
final Collection<Integer> arrayList2 = getBiggerThan(arrayList, 6);
System.out.println(arrayList2);
System.out.println(arrayList2.getClass());
System.out.println();
final Collection<Integer> set = new HashSet<>(arrayList);
final Collection<Integer> set2 = getBiggerThan(set, 6);
System.out.println(set2);
System.out.println(set2.getClass());
System.out.println();
// This does not work as Arrays.asList() is of a type
// java.util.Arrays$ArrayList which does not provide a nullary constructor
final Collection<Integer> numbers2 = getBiggerThan(numbers, 6);
}