Is there a sum() equivalent method in stream which can perform multiplication of values given in a stream?
I\'ve a list of Integers like this :
List
I contribute to @Misha answer because of I have found an example where we would want use BigInteger rather than primitive datatypes for multiplication.
I was solving this kata: Numbers with this digit inside, where we are given x: an int and d: a digit. We need to find the numbers from 1 to x which contain d, and return its count, sum and multiplication as a long array.
First I tried the following code:
import java.util.*;
public class Kata
{
public static long[] NumbersWithDigitInside(long x, long d)
{
if(d > x) return new long[3];
List list = new ArrayList();
for(int i = 1; i <= x; i++){
String current = String.valueOf(i);
if(current.contains(String.valueOf(d))){
list.add(i);
}
}
return new long[]{list.size(),
list.stream().mapToInt(Integer::intValue).sum(),
list.stream().reduce(1, (a,b) -> a*b)};
}
}
When we execute the following tests:
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import org.junit.runners.JUnit4;
public class SolutionTest {
@Test
public void BasicTests() {
assertArrayEquals(new long[] { 0, 0, 0 }, Kata.NumbersWithDigitInside(5, 6));
assertArrayEquals(new long[] { 1, 6, 6 }, Kata.NumbersWithDigitInside(7, 6));
assertArrayEquals(new long[] { 3, 22, 110 }, Kata.NumbersWithDigitInside(11, 1));
assertArrayEquals(new long[] { 2, 30, 200 }, Kata.NumbersWithDigitInside(20, 0));
assertArrayEquals(new long[] { 9, 286, 5955146588160L }, Kata.NumbersWithDigitInside(44, 4));
}
}
It outputs:
arrays first differed at element [2]; expected:<5955146588160> but was:<-1973051392>
Because of it fails when attempting the last test case:
assertArrayEquals(new long[] { 9, 286, 5955146588160L }, Kata.NumbersWithDigitInside(44, 4));
So to check if it was due to an overflown I replaced:
list.stream().reduce(1, (a,b) -> a*b)};
With:
list.stream().mapToInt(num->num).reduce(1, Math::multiplyExact)};
So then, it outputs:
java.lang.ArithmeticException: integer overflow
Finally I used BigInteger as follows:
list.stream().map(BigInteger::valueOf).reduce(BigInteger.ONE, BigInteger::multiply).longValue()}
Being the complete code:
import java.util.*;
import java.math.BigInteger;
public class Kata
{
public static long[] NumbersWithDigitInside(long x, long d)
{
List list = new ArrayList();
for(int i = 1; i <= x; i++){
String current = String.valueOf(i);
if(current.contains(String.valueOf(d))){
list.add(i);
}
}
if(list.size() == 0) return new long[3];
return new long[]{list.size(),
list.stream().mapToInt(Integer::intValue).sum(),
list.stream().map(BigInteger::valueOf).reduce(BigInteger.ONE, BigInteger::multiply).longValue()};
}
}
➡️ For further information:
BigInteger class longValue()