Gol*_*ict 2 java collections jpa java-8 java-stream
我正在使用Java 8(build 1.8.0_25),Netbeans 8.0.2,并将一些Java 8功能集成到现有应用程序中.排序和.forEach不起作用,所以我创建了一些测试代码,以确保我理解lambdas等,并诊断问题.下面是新代码和代码的混合,以便与我的系统中的数据进行交互:
public void test(Registration reg) {
/* new code */
List<String> family = new ArrayList<>();
family.add("Mom");
family.add("Dad");
family.add("Brother");
family.add("Sister");
family.forEach(p -> System.out.println(p));
Collections.sort(family, (p1,p2) -> {
System.out.println(p1 + " <==> "+ p2);
return p1.compareToIgnoreCase(p2);
});
family.forEach(p -> System.out.println(p));
/* code to test with my system data */
List<RegistrationItem> item = new ArrayList<>();
List<RegistrationItem> regI = reg.getRegistrationItem();
regI.forEach(p -> {
System.out.println(p.toString());
item.add(p);
});
Collections.sort(regI, (r1,r2) -> {
System.out.println(r1.toString() + r2.toString());
return r1.getId().compareTo(r2.getId());
});
for (RegistrationItem r : regI) {
item.add(r);
}
}
Run Code Online (Sandbox Code Playgroud)
注册是反映事件数据的POJO,其中包括作为另一个POJO详细信息的RegistrationItem列表.在此测试中,列表大小为4.
标有新代码的部分非常有效.它打印出列表,在排序时打印,然后打印排序列表.我也可以在排序块中设置断点,这是我所期望的.
使用现有代码是另一回事..forEach和.sort不起作用,我无法在java 8块中设置断点.调试器步骤到代码,但它似乎不执行.当我进入for循环时,"item"的大小仍为0.看上去就是为了证明数据可以移动,按预期工作,结果大小为4.
任何帮助,将不胜感激.
我道歉我可能不清楚.这只是测试代码,演示了我在更改为java 8后在数十个地方遇到的问题.比较器已更改为lambdas,而for循环更改为.forEach且没有任何工作正常.除了这个帖子之外,此代码没有其他目的.
在示例中,我已验证reg是否正确传递给测试方法.它的结构正确,regI的大小为4,具有正确结构的对象.
我假设我的环境或代码有问题,但我自己无法识别它.
在使用Holger和Stuart Marks建议的方法进行测试之后,很明显这与IndirectList和覆盖相关的问题相同.我的JRE和JDK都是Java 8,我已升级到EclipseLink 2.5.2.我已经证明了问题是100%的时间用比较器,Collections.sort与lambdas和.forEach发生.这似乎是一个非常普遍的问题,我很惊讶另一个问题并没有吸引更多的关注,而不是我的一个上升.
这个问题的根本原因是在IndirectListEclipseLink JPA类中使用了一个有缺陷的实现模式.(doc,source)此问题发生在2.5版本系列中; 它也可能出现在其他版本中.
问题是这个类既是子类 Vector又有对实例的引用Vector.它试图通过覆盖所有方法将所有方法调用委托给该实例Vector.只要没有添加新方法,这样就可以正常工作Vector.
这发生在Java 8中.
Java的8增加了几个新的默认方式为Collection,Iterable和List接口,包括:
forEachparallelStreamremoveIfreplaceAllsortspliteratorstream通常,添加默认方法是安全的,因为它们必须根据其他现有方法实现.但是,出于效率的原因,实现类以覆盖默认方法通常是个好主意.Java 8 Vector实现添加了这些默认方法的几个覆盖.如果你有一个实际Vector类的实例,这些工作正常.本IndirectList类不重写这些方法,所以它试图建立委托路径不为这些方法的工作.相反,使用普通Vector实现.不幸的是,这些IndirectList方法不会使超类状态保持最新,因此Vector方法的实现都表现为Vector空.
Vector覆盖forEach,removeIf,replaceAll,sort,和spliterator.在parallelStream与stream默认的方法是在以下方面实现的spliterator,于是同样的事情发生在他们身上.实际上,如果在IndirectListEclipseLink JPA中检索的实现上使用了集合上的新默认方法,则它们都不会起作用.
请注意,此问题也会发生Collections.sort(indirectList).此方法只调用该indirectList.sort()方法,因此它遇到与上述完全相同的问题.
此答案中列出了此问题的一些可能的解决方法.
有关EclipseLink状态的更多信息,请参阅EclipseLink JPA错误433075和446236.
有关此实现模式的缺陷的更多信息,请参阅Joshua Bloch的书" Effective Java,Second Edition,Item 16:Favor Composition over Inheritance".