如何使用java 8流将列表中的值相乘
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36833932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to multiply values in a list using java 8 streams
提问by
Is there a sum() equivalent method in stream which can perform multiplication of values given in a stream?
流中是否有 sum() 等效方法可以执行流中给定值的乘法?
I've a list of Integers like this :
我有一个像这样的整数列表:
List<Integer> listOfIntegers = new ArrayList<>();
listOfIntegers.addAll(Arrays.asList(1,4,2,7,5));
I'm able to get the sum of all the integers, but unable to find an API which can multiply the values and give the output.
我能够获得所有整数的总和,但无法找到可以将值相乘并给出输出的 API。
listOfIntegers.stream().mapToInt(a -> a).sum();
If I try to use forEach to do it, then I cannot store the result as only final variables are allowed to be used inside it.
如果我尝试使用 forEach 来做到这一点,那么我无法存储结果,因为只允许在其中使用最终变量。
Is there any alternative to this?
有什么替代方法吗?
采纳答案by Bandi Kishore
回答by Misha
One thing to keep in mind when multiplying an unknown number of ints
is the possibility of overflows. Rather than (a,b) -> a*b
, it is safer to use Math::multiplyExact
, which will throw an exception on overflow:
在乘以未知数时要记住的一件事ints
是溢出的可能性。而不是(a,b) -> a*b
,使用 更安全Math::multiplyExact
,它会在溢出时抛出异常:
listOfIntegers.stream().mapToInt(x->x).reduce(1, Math::multiplyExact);
Alternatively, you can accommodate large results by reducing on BigInteger
:
或者,您可以通过减少 来容纳较大的结果BigInteger
:
listOfIntegers.stream()
.map(BigInteger::valueOf)
.reduce(BigInteger.ONE, BigInteger::multiply);
Reduction with an identity will return 1
or BigInteger.ONE
if the list is empty, which may not be what you want. If you wish to handle the case of an empty list, remove the first argument to reduce
and then deal with the resulting Optional
.
带有身份的减少将返回,1
或者BigInteger.ONE
如果列表为空,这可能不是您想要的。如果您希望处理空列表的情况,请删除 的第一个参数reduce
,然后处理结果Optional
.
回答by Enoy
I contribute to @Misha answerbecause of I have found an example where we would want use BigInteger rather than primitive datatypes for multiplication.
我对@Misha 的回答做出了贡献,因为我找到了一个示例,在该示例中我们希望使用 BigInteger 而不是原始数据类型进行乘法。
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.
我正在解决这个 kata: Numbers with this digit inside,我们得到 x: an int 和 d: a digit。我们需要找到从 1 到 x 包含 d 的数字,并将其计数、总和和乘法作为一个长数组返回。
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<Integer> list = new ArrayList<Integer>();
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:
最后我使用 BigInteger 如下:
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<Integer> list = new ArrayList<Integer>();
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:
?? 了解更多信息: