1

AFAIK the only way to sum a stream of BigDecimal is:

BigDecimal result = stream.reduce(BigDecimal.ZERO, BigDecimal::add);

The problem here is that every call to BigDecimal::add will create a new BigDecimal as opposed to changing a mutable type.

Is there a mutable reduction operation aka Collector for Stream<BigDecimal>?

Roland
  • 7,525
  • 13
  • 61
  • 124
  • see this if it helps http://stackoverflow.com/questions/22635945/adding-up-bigdecimals-using-streams – Sanjit Kumar Mishra Jan 10 '17 at 13:36
  • 2
    unless one exists already you'd need something analogous to a `StringBuilder` (but for `BigDecimal`), since `BigDecimal` is immutable. – Rogue Jan 10 '17 at 13:45
  • 3
    “The problem here is …”—did you actually verify that there is such a problem, i.e. did a profiling tool tell you that? Modern JVMs are usually good at dealing with temporary objects created in a hot loop. You should only act when necessary, especially as a solution would require re-implementing parts of that existing class. – Holger Jan 10 '17 at 13:56
  • @Holger good point and no I didn't do any profiling, I was just surprised when I realized that there is no `Collector` for this purpose given that the purpose of `Collector` was to deal with this kind of situation. I was expecting the existence of `MutableBigInteger` or something analogous but maybe the JVM just optimizes the "problem" away. – Roland Jan 10 '17 at 15:12
  • 3
    Well, `Collector`s can deal with mutable types, if they exist, but a public mutable `BigDecimal` companion never existed and the future development will clearly go towards more JVM improvements (for the benefit of *all* value types) rather than adding a mutable helper class for every immutable class. – Holger Jan 10 '17 at 15:39
  • @Holger if you rewrite your comments as an answer I will make it the accepted one. – Roland Jan 10 '17 at 15:44

2 Answers2

5

BigDecimal: "Immutable, arbitrary-precision signed decimal numbers."

Since its immutable there is no method to manipulate them without creating new objects. Any method that can do that would break guarantees of the class (like BigDecimal.ZERO being 0)

Kiskae
  • 24,655
  • 2
  • 77
  • 74
  • Understood. But why is there no mutable accumulation version of `BigInteger` to create a `Collector`? I.e. why is there no `MutableBigInteger`? – Roland Jan 10 '17 at 15:10
  • 1
    Going by this comment from the Java implementers: http://bugs.java.com/bugdatabase/view_bug.do;jsessionid=813487c6e93a54f6f2f437bc69cd?bug_id=4379405 - They don't think such a class is required and the immutable implementation is enough when paired with JVM optimizations. – Kiskae Jan 10 '17 at 15:14
4

Well, there is no public mutable BigDecimal companion class, so there is no Collector using it. But you should not worry about the performance implication of the instance creation unless a profiling tool tells you that there is a problem.

Modern JVMs like HotSpot are usually good at dealing with temporary objects created in a hot loop. Even if they are not able to elide the allocation, the allocation costs are not so big. This is different to, e.g. String::concat where the instance creation costs do not only include the allocation, but copying the entire contents of the previously created String instances, yielding a quadratic time complexity of such reduction (unless the optimizer manages to rewrite such code). The same would apply to attempts to produce a Collection via pure (immutable) reduction.

This might be contradicting to the existence of primitive type specializations like IntStream, LongStream and DoubleStream, but that’s a trade-off. Generally, the preference of the JRE developers is towards improving the JVM performance (for the benefit of all value types) rather than adding a mutable helper class for every immutable class. There might be a continuity of special support for primitive types until the arrival of full value type support, but don’t expect the addition of new public mutable companion classes for immutable types (unless we’re talking about construction costs like in the String example).

Holger
  • 285,553
  • 42
  • 434
  • 765