【发布时间】:2015-12-13 21:28:10
【问题描述】:
我想要一种简单的方法来连接 Iterables,所以我在 Spring MVC 代码(Spring 4.2.1)中尝试了 Guava Iterables(19 RC1)。
我有两个来自 Spring Data JPA 的迭代。例如
Iterable<Portfolio> result = portfRepository.findBySomeCriteria();
Iterable<Portfolio> result2 = portfRepository.findByOtherCriteria();
然后我做一个连接:
Iterable<Portfolio> combined = Iterables.concat(result, result2);
但是当 Jackson 处理组合的 Iterable 时,它只显示 { empty: false } 而不是投资组合数组。
我查看了 Guava 的 concat 实现。它基本上返回两个 Iterable 的 ImmutableList,并提供了一个重写的 Iterator,它知道如何遍历第一个 Iterable,然后是第二个 Iterable。
/**
* Combines two iterables into a single iterable. The returned iterable has an
* iterator that traverses the elements in {@code a}, followed by the elements
* in {@code b}. The source iterators are not polled until necessary.
*
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*/
public static <T> Iterable<T> concat(
Iterable<? extends T> a, Iterable<? extends T> b) {
return concat(ImmutableList.of(a, b));
}
/**
* Combines multiple iterables into a single iterable. The returned iterable
* has an iterator that traverses the elements of each iterable in
* {@code inputs}. The input iterators are not polled until necessary.
*
* <p>The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it. The methods of the returned
* iterable may throw {@code NullPointerException} if any of the input
* iterators is null.
*/
public static <T> Iterable<T> concat(
final Iterable<? extends Iterable<? extends T>> inputs) {
checkNotNull(inputs);
return new FluentIterable<T>() {
@Override
public Iterator<T> iterator() {
return Iterators.concat(iterators(inputs));
}
};
}
问题是,Java 8 Iterable API 提供了新方法:
default void forEach(Consumer<? super T> action)
default Spliterator<T> spliterator()
我猜如果某些代码(在本例中为 Spring MVC 或 Jackson)使用这些方法循环遍历 Iterable 而不是迭代器方法,那么作为 Iterables 列表的串联 Guava Iterable 可能无法工作。有人可以证实这一点吗?谢谢。
【问题讨论】:
-
这不是很容易自己测试吗?
-
Iterable被 Jackson 渲染为{"empty": false}的事实表明 Jackson 不支持开箱即用的Iterables,至少在您使用的版本中:它不知道它应该对其进行迭代,所以它只是渲染了唯一看起来像属性的东西,即isEmpty()方法。 -
此外,像
forEach()这样的“默认方法”是添加到Java 8 中现有接口的方法具有默认实现(因此得名)以提供向后兼容性,因此在这种情况下,它们适用于任何Iterable。 -
@FrankPavageau 如果我只返回一个 Iterable(比如结果),Jackson 可以正确转换它。这没有问题。正如我在上面的帖子中所说,我认为这是由于 Guava 将 Iterable 实现为 Iterables 的 ImmutableList。
-
不,默认方法不是这样工作的:它们为接口的所有实现者提供新方法的实现,它们不能“不工作”(抛出异常可能是可接受的“工作”,但这里不是这种情况)。当您返回
Iterable时,它可能会起作用,因为该对象的实际类型是 Jackson 已知的,例如ArrayList。 Guava 使用ImmutableList实现concat()和匿名FluentIterable,而不是ImmutableList本身,所以它实际上只是一个Iterable而不是Collection的子类。
标签: java spring iterator guava iterable