BiConsumer无法修改参数

时间:2014-09-30 06:30:11

标签: java-8 immutability collectors

我为java 8流实现了一个收集器,当达到给定的阈值时,它将实体存储到存储库。

public BiConsumer<Tuple2<Integer,List<T>>, T> accumulator() {
    return (tuple, e) -> {
        List<T> list = tuple._2;
        list.add(e);
        if (list.size() >= this.threshold) {
            this.repository.save(list);
            this.repository.flush();
            list = new LinkedList<>();
        }
        tuple = new Tuple2<>(tuple._1 + 1, list);
    };
}

这不按预期工作。元素e被添加到列表中,但在达到阈值后不会重置。整数也保持在0,这是自最终成员以来的预期。 因为看起来我唯一的选择是使我的Tuple2可变并清空列表:-( 有关如何使用不可变元组解决这个问题的任何建议吗?

2 个答案:

答案 0 :(得分:1)

lambda表达式可以被认为是一个没有名称的函数(或方法)。在这个例子中,它就像一个方法,它有两个形式参数tuplee,还有一些局部变量,包括list

当您对形式参数或局部变量进行赋值时,该赋值对于当前方法(或lambda体)是本地的。累加器返回后,外部不会看到任何突变或副作用,因此这些分配不会影响您收集的数据结构。

我不完全确定你要做什么,但是你可能会尝试编写一个包含整数计数器的普通可变类,而不是使用元组(可能是不可变的,必须替换而不是变异)。 (或其他)和清单。累加器将添加到列表中,有条件地刷新并替换列表,并递增计数器。这些变异操作在收集器中是允许的,因为收集器框架仔细地线程限制了这些操作,因此您正在变异的对象不需要是线程安全的。

答案 1 :(得分:-3)

它不工作的原因仅仅是我为参考“元组”分配了一个新值。这是一个call-by-reference方法参数,因此是对我可以修改的外部对象的引用。但我无法修改外部引用本身。

因此,当我为tuple分配一个新实例时,我得到一个新对象,该对象与最初作为函数参数移交的对象无关。

这是 - 可耻的 - 我应该知道的事情。