diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java
index e3659496c..af022870d 100644
--- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java
@@ -1,12 +1,25 @@
package cn.hutool.core.stream;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Opt;
+import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjUtil;
-
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
import java.util.Objects;
+import java.util.OptionalDouble;
import java.util.Spliterator;
-import java.util.function.*;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongFunction;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -97,7 +110,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型
* @return 包含单个元素的串行流
*/
@@ -109,9 +122,9 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型
+ * @param 元素类型
* @return 包含指定元素的串行流
- * 从一个安全数组中创建流
+ * 从一个安全数组中创建流
*/
@SafeVarargs
@SuppressWarnings("varargs")
@@ -123,7 +136,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型
+ * @param 元素类型
* @return 流
*/
public static EasyStream of(final Iterable iterable) {
@@ -135,7 +148,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型
+ * @param 元素类型
* @return 流
*/
public static EasyStream of(final Iterable iterable, final boolean parallel) {
@@ -150,7 +163,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型
+ * @param 元素类型
* @return 流
*/
public static EasyStream of(final Stream stream) {
@@ -166,9 +179,9 @@ public class EasyStream extends AbstractEnhancedWrappedStream
*
- * @param 元素类型
+ * @param 元素类型
* @param seed 初始值
- * @param f 用上一个元素作为参数执行并返回一个新的元素
+ * @param f 用上一个元素作为参数执行并返回一个新的元素
* @return 无限有序流
*/
public static EasyStream iterate(final T seed, final UnaryOperator f) {
@@ -184,13 +197,14 @@ public class EasyStream extends AbstractEnhancedWrappedStream
*
- * @param 元素类型
- * @param seed 初始值
+ * @param 元素类型
+ * @param seed 初始值
* @param hasNext 条件值
- * @param next 用上一个元素作为参数执行并返回一个新的元素
+ * @param next 用上一个元素作为参数执行并返回一个新的元素
* @return 无限有序流
*/
- public static EasyStream iterate(final T seed, final Predicate super T> hasNext, final UnaryOperator next) {
+ public static EasyStream iterate(final T seed, final Predicate super T> hasNext,
+ final UnaryOperator next) {
Objects.requireNonNull(next);
Objects.requireNonNull(hasNext);
return new EasyStream<>(StreamUtil.iterate(seed, hasNext, next));
@@ -198,11 +212,11 @@ public class EasyStream extends AbstractEnhancedWrappedStream 元素类型
- * @param s 用来生成元素的 {@code Supplier}
+ * @param s 用来生成元素的 {@link Supplier}
* @return 无限串行无序流
*/
public static EasyStream generate(final Supplier s) {
@@ -217,8 +231,8 @@ public class EasyStream extends AbstractEnhancedWrappedStream从重复串行流进行拼接时可能会导致深度调用链甚至抛出 {@code StackOverflowException}
*
* @param 元素类型
- * @param a 第一个流
- * @param b 第二个流
+ * @param a 第一个流
+ * @param b 第二个流
* @return 拼接两个流之后的流
*/
public static EasyStream concat(final Stream extends T> a, final Stream extends T> b) {
@@ -228,12 +242,13 @@ public class EasyStream extends AbstractEnhancedWrappedStream split(final CharSequence str, final String regex) {
- return Opt.ofBlankAble(str).map(CharSequence::toString).map(s -> s.split(regex)).map(EasyStream::of).orElseGet(EasyStream::empty);
+ return Opt.ofBlankAble(str).map(CharSequence::toString).map(s -> s.split(regex)).map(EasyStream::of)
+ .orElseGet(EasyStream::empty);
}
// --------------------------------------------------------------- Static method end
@@ -244,7 +259,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream 函数执行后返回的类型
+ * @param 函数执行后返回的类型
* @return 返回叠加操作后的流
*/
@Override
@@ -264,6 +279,125 @@ public class EasyStream extends AbstractEnhancedWrappedStream(stream);
}
+
+ /**
+ * 计算int类型的总和
+ *
+ * @param mapper 将对象转换为int的 {@link Function}
+ * @return int 总和
+ */
+ public int sum(final ToIntFunction super T> mapper) {
+ return stream.mapToInt(mapper).sum();
+ }
+
+ /**
+ * 计算long类型的总和
+ *
+ * @param mapper 将对象转换为long的 {@link Function}
+ * @return long 总和
+ */
+ public long sum(final ToLongFunction super T> mapper) {
+ return stream.mapToLong(mapper).sum();
+ }
+
+
+ /**
+ * 计算double类型的总和
+ *
+ * @param mapper 将对象转换为double的 {@link Function}
+ * @return double 总和
+ */
+ public double sum(final ToDoubleFunction super T> mapper) {
+ return stream.mapToDouble(mapper).sum();
+ }
+
+
+ /**
+ * 计算 {@link Number} 类型的总和
+ *
+ * @param 数字
+ * @param mapper 将对象转换为{@link Number} 的 {@link Function}
+ * @return {@link BigDecimal} , 如果流为空, 返回 {@link BigDecimal#ZERO}
+ */
+ public BigDecimal sum(final Function super T, R> mapper) {
+ return stream.map(mapper).reduce(BigDecimal.ZERO, NumberUtil::add, NumberUtil::add);
+ }
+
+
+ /**
+ * 计算 {@link BigDecimal} 类型的平均值 并以四舍五入的方式保留2位精度
+ *
+ * @param mapper 将对象转换为{@link BigDecimal}的 {@link Function}
+ * @return 计算后的平均值 如果流的长度为0, 返回 {@link Opt#empty()}
+ */
+ public Opt avg(final Function super T, BigDecimal> mapper) {
+ return avg(mapper, 2);
+ }
+
+
+ /**
+ * {@link BigDecimal} 类型的平均值 并以四舍五入的方式保留小数点后scale位
+ *
+ * @param mapper 将对象转换为{@link BigDecimal} 的 {@link Function}
+ * @param scale 保留精度
+ * @return 计算后的平均值 如果流的长度为0, 返回 {@link Opt#empty()}
+ */
+ public Opt avg(final Function super T, BigDecimal> mapper, final int scale) {
+ return avg(mapper, scale, RoundingMode.HALF_UP);
+ }
+
+ /**
+ * 计算 {@link BigDecimal} 类型的平均值
+ *
+ * @param mapper 将对象转换为{@link BigDecimal} 的 {@link Function}
+ * @param scale 保留精度
+ * @param roundingMode 舍入模式
+ * @return 计算后的平均值 如果元素的长度为0 那么会返回 {@link Opt#empty()}
+ */
+ public Opt avg(final Function super T, BigDecimal> mapper, final int scale,
+ final RoundingMode roundingMode) {
+ //元素列表
+ List bigDecimalList = stream.map(mapper).collect(Collectors.toList());
+ if (CollUtil.isEmpty(bigDecimalList)) {
+ return Opt.empty();
+ }
+ return Opt.ofNullable(EasyStream.of(bigDecimalList).reduce(BigDecimal.ZERO, BigDecimal::add)
+ .divide(NumberUtil.toBigDecimal(bigDecimalList.size()), scale, roundingMode));
+ }
+
+
+ /**
+ * 计算int类型的平均值
+ *
+ * @param mapper 将对象转换为int 的 {@link Function}
+ * @return {@link OptionalDouble} 如果流的长度为0 那么会返回{@link OptionalDouble#empty()}
+ */
+ public OptionalDouble avg(final ToIntFunction super T> mapper) {
+ return stream.mapToInt(mapper).average();
+ }
+
+ /**
+ * 计算double类型的平均值
+ *
+ * @param mapper 将对象转换为double 的 {@link Function}
+ * @return {@link OptionalDouble} 如果流的长度为0 那么会返回{@link OptionalDouble#empty()}
+ */
+ public OptionalDouble avg(final ToDoubleFunction super T> mapper) {
+ return stream.mapToDouble(mapper).average();
+ }
+
+
+ /**
+ * 计算double平均值
+ *
+ * @param mapper 将对象转换为long 的 {@link Function}
+ * @return {@link OptionalDouble} 如果流的长度为0 那么会返回{@link OptionalDouble#empty()}
+ */
+ public OptionalDouble avg(final ToLongFunction super T> mapper) {
+ return stream.mapToLong(mapper).average();
+ }
+
+
/**
* 建造者
*
@@ -277,12 +411,12 @@ public class EasyStream extends AbstractEnhancedWrappedStream{@code
- * accept(t)
- * return this;
- * }
+ * {@code
+ * accept(t)
+ * return this;
+ * }
*/
default Builder add(final T t) {
accept(t);
diff --git a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java
index 0f50b8337..2fa800d3a 100644
--- a/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/stream/EasyStreamTest.java
@@ -1,16 +1,31 @@
package cn.hutool.core.stream;
-import cn.hutool.core.collection.ListUtil;
-import cn.hutool.core.map.MapUtil;
-import org.junit.Assert;
-import org.junit.Test;
+import static java.util.Collections.singletonList;
-import java.util.*;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.lang.Opt;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.math.NumberUtil;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.OptionalDouble;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-
-import static java.util.Collections.singletonList;
+import org.junit.Assert;
+import org.junit.Test;
/**
* @author VampireAchao
@@ -181,7 +196,8 @@ public class EasyStreamTest {
Assert.assertEquals(ListUtil.sort(collect2), ListUtil.sort(distinctBy2));
Assert.assertEquals(
- 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true).distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count()
+ 4, EasyStream.of(1, 2, 2, null, 3, null).parallel(true)
+ .distinct(t -> Objects.isNull(t) ? null : t.toString()).sequential().count()
);
}
@@ -433,4 +449,110 @@ public class EasyStreamTest {
Assert.assertTrue(EasyStream.of(1).isNotEmpty());
}
+
+ @Test
+ public void testIntSumAndAvg() {
+ //测试int类型的总和
+ int sum = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).sum(Integer::intValue);
+ Assert.assertEquals(55, sum);
+
+ //测试为空
+ List integerList = new ArrayList<>();
+ int emptySum = EasyStream.of(integerList).sum(Integer::intValue);
+ Assert.assertEquals(0, emptySum);
+
+ //测试平均值
+ OptionalDouble avg = EasyStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).avg(Integer::intValue);
+ Assert.assertTrue(avg.isPresent());
+ Assert.assertEquals(5.5, avg.getAsDouble(), 2);
+
+ //测试元素为空
+ OptionalDouble emptyAvg = EasyStream.of(integerList).avg(Integer::intValue);
+ Assert.assertFalse(emptyAvg.isPresent());
+
+ }
+
+ @Test
+ public void testDoubleSumAndAvg() {
+ //测试double类型的sum
+ double doubleSum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).sum(Double::doubleValue);
+ Assert.assertEquals(59.6, doubleSum, 2);
+
+ //测试double类型的sum 无元素double
+ List doubleList = new ArrayList<>();
+ double emptySum = EasyStream.of(doubleList).sum(Double::doubleValue);
+ Assert.assertEquals(0.0, emptySum, 2);
+
+ //测试double类型的avg
+ OptionalDouble doubleAvg = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+ .avg(Double::doubleValue);
+ Assert.assertTrue(doubleAvg.isPresent());
+ Assert.assertEquals(5.96, doubleAvg.getAsDouble(), 2);
+
+ //测试double类型的 空元素的avg
+ OptionalDouble emptyDoubleAvg = EasyStream.of(doubleList).avg(Double::doubleValue);
+ Assert.assertFalse(emptyDoubleAvg.isPresent());
+
+ }
+
+ @Test
+ public void testLongSumAndAvg() {
+ //测试long类型的sum
+ long sum = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).sum(Long::longValue);
+ Assert.assertEquals(55L, sum);
+
+ //测试long类型的空元素 sum
+ List longList = new ArrayList<>();
+ long emptySum = EasyStream.of(longList).sum(Long::longValue);
+ Assert.assertEquals(0L, emptySum);
+
+ //测试long类型的avg
+ OptionalDouble doubleAvg = EasyStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L).avg(Long::longValue);
+ Assert.assertTrue(doubleAvg.isPresent());
+ Assert.assertEquals(5.5, doubleAvg.getAsDouble(), 2);
+
+ //测试long类型的avg 空元素
+ OptionalDouble emptyDoubleAvg = EasyStream.of(longList).avg(Long::longValue);
+ Assert.assertFalse(emptyDoubleAvg.isPresent());
+
+
+ }
+
+ @Test
+ public void testBigDecimalSumAndAvg() {
+ //测试bigDecimal的sum
+ BigDecimal sum = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10).map(NumberUtil::toBigDecimal)
+ .sum(Function.identity());
+ Assert.assertEquals(NumberUtil.toBigDecimal(59.6), sum);
+
+ //测试bigDecimal的sum 空元素
+ List bigDecimalEmptyList = new ArrayList<>();
+ BigDecimal emptySum = EasyStream.of(bigDecimalEmptyList).sum(Function.identity());
+ Assert.assertEquals(BigDecimal.ZERO, emptySum);
+
+ //测试bigDecimal的avg全参
+ Opt bigDecimalAvgFullParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+ .map(NumberUtil::toBigDecimal)
+ .avg(Function.identity(), 2, RoundingMode.HALF_UP);
+ Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgFullParam.get());
+
+ //测试bigDecimal的avg单参
+ Opt bigDecimalAvgOneParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+ .map(NumberUtil::toBigDecimal)
+ .avg(Function.identity());
+ Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgOneParam.get());
+
+ //测试bigDecimal的avg双参
+ Opt bigDecimalAvgTwoParam = EasyStream.of(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10)
+ .map(NumberUtil::toBigDecimal)
+ .avg(Function.identity(), 2);
+ Assert.assertEquals(NumberUtil.toBigDecimal(5.96), bigDecimalAvgTwoParam.get());
+
+ //测试bigDecimal的avg 空元素
+ Opt emptyBigDecimalAvg = EasyStream.of(bigDecimalEmptyList)
+ .avg(Function.identity(), 2, RoundingMode.HALF_UP);
+ Assert.assertFalse(emptyBigDecimalAvg.isPresent());
+
+
+ }
}