Java 8 Stream:迭代,处理和计数

时间:2015-11-26 16:59:49

标签: java java-8 java-stream side-effects

以这种方式处理和统计处理过的数据是否可以?

long count = userDao.findApprovedWithoutData().parallelStream().filter(u -> {
    Data d = dataDao.findInfoByEmail(u.getEmail());
    boolean ret = false;
    if (d != null) {
        String result = "";
        result += getFieldValue(d::getName, ". \n");
        result += getFieldValue(d::getOrganization, ". \n");
        result += getFieldValue(d::getAddress, ". \n");
        if(!result.isEmpty()) {
            u.setData(d.getInfo());
            userDao.update(u);
            ret = true;
        }
    }
    return ret;
}).count();

因此,简而言之:迭代不完整的记录,如果数据存在则更新并计算此记录数量?

2 个答案:

答案 0 :(得分:5)

恕我直言,这是错误的代码,因为:

过滤谓词具有(非常显着的)副作用

谓词不应该有副作用(就像吸气者不应该这样)。这是意料之外的,这使它变得糟糕。

过滤谓词非常低效

每次执行谓词都会导致大量查询被触发,这使得此代码无法扩展。

乍一看,主要目的似乎是计算,但实际上这是一个小的(可有可无的)信息

良好的代码使得显而易见的事情(与此代码不同)

您应该更改代码以使用(相当简单的)单个更新查询(使用连接)并从更新的行数中获取计数"持久性API的结果中的信息。

答案 1 :(得分:1)

这取决于您对process的定义。我不能给你一个明确的yes or no,因为我认为很难在不理解你的代码及其实现方式的情况下得出结论。

您正在使用并行流,并且Java运行时会根据ForkJoinPool的公共池中的可用线程数将Stream拆分为子流。

使用parallelism时,您需要注意可能的副作用:

  1. 干扰(流中的 Lambda 表达式不应干扰)
  2.   

    流操作中的Lambda表达式不应该干扰。   当a的流源被修改时发生干扰   管道处理流。

    1. Statetful Lambda表达式
    2.   

      避免在流中使用有状态lambda表达式作为参数   操作。有状态的lambda表达式是结果所依赖的表达式   在任何可能在执行管道期间发生变化的状态。

      查看您的问题并将上述要点应用于此。

      无干扰>强烈声明Lambda表达式在管道操作期间不应干扰流的源(除非流源是并发的),因为它可能导致:

      • 异常(即ConcurrentModificationException)
      • 错误答案
      • 不一致的行为

      除了在中间操作(即过滤器)中进行修改的行为良好的流之外,请在here中阅读更多内容。

      您的Lambda表达式确实会干扰流的来源,但不建议这样做,但干扰是在中级操作中,现在一切都归结为流是否表现良好。因此,在涉及干扰时,您可能会考虑重新考虑您的lambda表达式。它也可能归结为您如何通过userDao.udpate更新流的来源,这在您的问题中并不明确。

      有状态Lambda表达式>您的Lambda表达式似乎不是有状态的,这是因为Lambda的结果取决于在执行管道期间不会更改的值/ s。所以这不适用于您的情况。

      我建议您阅读Java 8 Stream以及此blog的文档,其中通过示例很好地解释了Java 8 Stream。