【问题标题】:Guava Iterables concat implementation does not work with new Iterable API methods added in Java 8?Guava Iterables concat 实现不适用于 Java 8 中添加的新 Iterable API 方法?
【发布时间】: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


【解决方案1】:

你需要以下依赖:

This adds support for Guava specific datatypes.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-guava</artifactId>
    <version>2.6.2</version>
</dependency>

您可能在某些时候也需要JDK8 datatypes

【讨论】:

    猜你喜欢
    • 2016-06-16
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多