【问题标题】:Why does this stream return no element?为什么这个流不返回任何元素?
【发布时间】:2015-11-03 13:32:06
【问题描述】:

我尝试将以下代码编写为流:

AbstractDevice myDevice = null;

for (AbstractDevice device : session.getWorkplace().getDevices()) {

    if (device.getPluginconfig().getPluginType().getId() == 1) {
        myDevice =  device;
    }

}

这段代码运行良好。

但是当我这样重写它时,它不再起作用了:

myDevice = session.getWorkplace().getDevices().stream()
                  .filter(s -> s.getPluginconfig().getPluginType().getId() == 1)
                  .findFirst().get();

我从流中返回的Optional 中没有任何值。为什么?

编辑

当我尝试这个时(我仍然从getDevices() 得到两台设备):

 List<AbstractDevice> testList = session.getWorkplace().getDevices()
                                        .stream().collect(Collectors.toList());

testList 为空。所以我的List 设备流似乎有问题?

这是一个 JavaEE 应用程序,我从相应的实体获取我的设备:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
@JoinTable(name = "Workplace_AbstractDevice",
            joinColumns = {
                @JoinColumn(name = "Workplace", referencedColumnName = "ID")
            },
            inverseJoinColumns = {
                @JoinColumn(name = "AbstractDevice", referencedColumnName = "ID")
            })
@OrderColumn
private List<AbstractDevice> devices = new ArrayList<AbstractDevice>();


public List<AbstractDevice> getDevices() {
    return devices;
}

【问题讨论】:

  • 你能提供一个简短但完整的程序来演示这个问题吗?如果无法重现,就很难诊断。
  • 原始代码将获得列表中最后一个匹配项,而流代码将获得第一个。我不知道这是否是这种情况下的问题。
  • "我从 session.getWorkplace.getDevices() 返回的列表中有两个对象" 你确定吗?此外,您的非流解决方案似乎找到了最后一个匹配而不是第一个。
  • 如果没有代码就无法回答这个问题,这会让我们重现问题。我们所能做的就是猜测,这不是很有效。请提供SSCCE,否则这个问题可能会被关闭。
  • 听起来你程序的其他部分非常很重要,因为它提供了没有被正确读取的数据......如果你回到你的原始代码,那仍然有效吗?

标签: java jpa java-8 eclipselink java-stream


【解决方案1】:

似乎您使用的是 2.6 版本之前的 EclipseLink 并点击了Bug#433075。这个devices 字段被替换为IndirectList(通过反射),它扩展了Vector 类并执行延迟初始化。它是为没有 stream() 方法的旧 Java 版本编写的,因此实际上在返回空流的未初始化列表上调用了 stream()

错误是fixed,因此您可能需要将 EclipseLink 更新到 2.6 版本。在 EclipseLink 2.6 中,另一个类是 used when running on JDK 1.8,它是流友好的。

【讨论】:

  • 谢谢!!但不幸的是,在 2.6 中使用@OrderColumn 时仍然是一个错误
  • @Swiss_Codeaholic,我明白了。真遗憾。您可以调用 devices.isEmpty() 之类的东西来强制初始化,但我建议在下一个版本发布之前不要使用流 API。
  • 是的,我现在放弃了。有点遗憾的是它仍然不受支持......我的意思是 JDK8 已经有一段时间了。无论如何,感谢您的帮助@Tagir Valeev!
  • 谢谢,我使用 eclipselink v2.5.0 的行为与此完全相同,但在 2.6.0 版本中问题消失了
猜你喜欢
  • 1970-01-01
  • 2021-04-30
  • 2020-09-28
  • 1970-01-01
  • 2018-01-24
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
相关资源
最近更新 更多