来自JPA的Java Lambda迭代列表



在将lambda与JPA一起使用时,我发现了一些奇怪的行为,似乎java 8 lambda在从另一个对象获取列表时不会迭代。

例如:

    List<MyObject> list = anotherObject.getMyObjectList(); // Get The List
    list.foreach(myobject -> System.out.println("NOT PRINTED"));
    System.out.println("Size?: " + list.size()); // Print The Size = 2

我尝试使用list.stream().foreach(),结果相同。。

经过几个小时的测试,我发现了一个技巧

    List<MyObject> copyList = new ArrayList<>(list); // copy The List 
    copyList.foreach(myobject -> System.out.println("OMG IS PRINTED!"));

嗯?有什么想法吗?,这是个虫子吗?还是我做错了什么?我的实体冲突运行良好,所有关系良好…:)

提前感谢:)。

最好知道anotherObject.getMyObjectList()返回的List的具体类。它的迭代器中可能有一个错误。

当您使用new ArrayList<>(list)将其复制到ArrayList时,此构造函数的代码将使用toArray从源列表中复制元素,然后将元素复制到包含在ArrayList中的新数组中。

当您调用list.forEach时,除非它被具体类覆盖,否则它最终会调用Iterable的默认方法forEach,其实现为:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

这只是一个标准的增强循环,没有什么神奇之处。但是这个for循环是根据列表的迭代器来实现的。试着写一个for循环,而不是调用list.forEach(lambda),或者试着调用list.iterator(),看看你从中得到了多少元素。如果toArray有效,但迭代技术不起作用,那么这似乎是JPA列表类迭代器实现中的一个错误。

更新您的EclipseLink版本,这个错误已经修复!

Bug:https://bugs.eclipse.org/bugs/show_bug.cgi?id=433075

更新至2.6.0或更高版本:http://mvnrepository.com/artifact/org.eclipse.persistence/eclipselink/2.6.0

最新更新