diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/collection/CollUtil.java index fd067d2bd..a189b8889 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/collection/CollUtil.java @@ -1554,7 +1554,7 @@ public class CollUtil { // String按照逗号分隔的列表对待 final String arrayStr = StrUtil.unWrap((CharSequence) value, '[', ']'); iter = SplitUtil.splitTrim(arrayStr, StrUtil.COMMA).iterator(); - } else if(value instanceof Map && BeanUtil.isWritableBean(TypeUtil.getClass(elementType))){ + } else if (value instanceof Map && BeanUtil.isWritableBean(TypeUtil.getClass(elementType))) { //https://github.com/dromara/hutool/issues/3139 // 如果值为Map,而目标为一个Bean,则Map应整体转换为Bean,而非拆分成Entry转换 iter = new ArrayIter<>(new Object[]{value}); @@ -2354,4 +2354,47 @@ public class CollUtil { } return collection.stream().allMatch(predicate); } + + /** + * 解构多层集合 + * 例如:{@code List>> 解构成 List} + * + * @param collection 需要解构的集合 + * @return 解构后的集合 + */ + public static List flat(Collection collection) { + return flat(collection, true); + } + + /** + * 解构多层集合 + * 例如:{@code List>> 解构成 List} + *

+ * skipNull如果为true, 则解构后的集合里不包含null值,为false则会包含null值。 + * + * @param collection 需要结构的集合 + * @param skipNull 是否跳过空的值 + * @return 解构后的集合 + */ + @SuppressWarnings({"unchecked"}) + public static List flat(Collection collection, boolean skipNull) { + LinkedList queue = new LinkedList<>(collection); + + List result = new ArrayList<>(); + + while (!queue.isEmpty()) { + Object t = queue.removeFirst(); + + if (skipNull && t == null) { + continue; + } + + if (t instanceof Collection) { + queue.addAll((Collection) t); + } else { + result.add(t); + } + } + return (List) result; + } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/stream/TransformableWrappedStream.java b/hutool-core/src/main/java/org/dromara/hutool/core/stream/TransformableWrappedStream.java index 5eed41ae1..718472d1c 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/stream/TransformableWrappedStream.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/stream/TransformableWrappedStream.java @@ -13,6 +13,7 @@ package org.dromara.hutool.core.stream; import org.dromara.hutool.core.array.ArrayUtil; +import org.dromara.hutool.core.collection.CollUtil; import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.collection.iter.IterUtil; import org.dromara.hutool.core.lang.Console; @@ -486,6 +487,17 @@ public interface TransformableWrappedStream childrenSetter.accept(e, null))); } + /** + * 如果当前元素是集合,则会将集合中的元素解构出来 + * 例如:{@code List>> 解构成 List} + * + * @param 函数执行后返回的List里面的类型 + * @return EasyStream 一个流 + */ + default EasyStream flat() { + return EasyStream.of(CollUtil.flat(nonNull().collect(Collectors.toList()))); + } + // endregion // region ============ map ============ diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/collection/CollUtilTest.java index bafe98d16..91ee1ff88 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/collection/CollUtilTest.java @@ -1,5 +1,6 @@ package org.dromara.hutool.core.collection; +import lombok.*; import org.dromara.hutool.core.collection.iter.IterUtil; import org.dromara.hutool.core.collection.set.SetUtil; import org.dromara.hutool.core.comparator.CompareUtil; @@ -7,33 +8,12 @@ import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.lang.Console; import org.dromara.hutool.core.map.Dict; import org.dromara.hutool.core.map.MapUtil; +import org.dromara.hutool.core.stream.EasyStream; import org.dromara.hutool.core.text.StrUtil; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.ToString; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Queue; -import java.util.Set; -import java.util.SortedSet; -import java.util.Stack; +import java.util.*; import java.util.function.Function; /** @@ -460,9 +440,9 @@ public class CollUtilTest { @Test public void sortByPropertyTest() { final List list = ListUtil.of( - new TestBean("张三", 12, DateUtil.parse("2018-05-01")), // - new TestBean("李四", 13, DateUtil.parse("2018-03-01")), // - new TestBean("王五", 12, DateUtil.parse("2018-04-01"))// + new TestBean("张三", 12, DateUtil.parse("2018-05-01")), // + new TestBean("李四", 13, DateUtil.parse("2018-03-01")), // + new TestBean("王五", 12, DateUtil.parse("2018-04-01"))// ); CollUtil.sortByProperty(list, "createTime"); @@ -474,9 +454,9 @@ public class CollUtilTest { @Test public void sortByPropertyTest2() { final List list = ListUtil.of( - new TestBean("张三", 0, DateUtil.parse("2018-05-01")), // - new TestBean("李四", -12, DateUtil.parse("2018-03-01")), // - new TestBean("王五", 23, DateUtil.parse("2018-04-01"))// + new TestBean("张三", 0, DateUtil.parse("2018-05-01")), // + new TestBean("李四", -12, DateUtil.parse("2018-03-01")), // + new TestBean("王五", 23, DateUtil.parse("2018-04-01"))// ); CollUtil.sortByProperty(list, "age"); @@ -488,8 +468,8 @@ public class CollUtilTest { @Test public void fieldValueMapTest() { final List list = ListUtil.of(new TestBean("张三", 12, DateUtil.parse("2018-05-01")), // - new TestBean("李四", 13, DateUtil.parse("2018-03-01")), // - new TestBean("王五", 12, DateUtil.parse("2018-04-01"))// + new TestBean("李四", 13, DateUtil.parse("2018-03-01")), // + new TestBean("王五", 12, DateUtil.parse("2018-04-01"))// ); final Map map = CollUtil.fieldValueMap(list, "name"); @@ -501,8 +481,8 @@ public class CollUtilTest { @Test public void fieldValueAsMapTest() { final List list = ListUtil.of(new TestBean("张三", 12, DateUtil.parse("2018-05-01")), // - new TestBean("李四", 13, DateUtil.parse("2018-03-01")), // - new TestBean("王五", 14, DateUtil.parse("2018-04-01"))// + new TestBean("李四", 13, DateUtil.parse("2018-03-01")), // + new TestBean("王五", 14, DateUtil.parse("2018-04-01"))// ); final Map map = CollUtil.fieldValueAsMap(list, "name", "age"); @@ -669,7 +649,7 @@ public class CollUtilTest { @Test public void subInput1PositiveNegativePositiveOutputArrayIndexOutOfBoundsException() { - Assertions.assertThrows(IndexOutOfBoundsException.class, ()->{ + Assertions.assertThrows(IndexOutOfBoundsException.class, () -> { // Arrange final List list = new ArrayList<>(); list.add(null); @@ -821,8 +801,8 @@ public class CollUtilTest { oldMap.put("c", "134"); final Map map = IterUtil.toMap(oldMap.entrySet(), - Map.Entry::getKey, - entry -> Long.parseLong(entry.getValue())); + Map.Entry::getKey, + entry -> Long.parseLong(entry.getValue())); Assertions.assertEquals(1L, (long) map.get("a")); Assertions.assertEquals(12L, (long) map.get("b")); @@ -900,12 +880,12 @@ public class CollUtilTest { public void setValueByMapTest() { // https://gitee.com/dromara/hutool/pulls/482 final List people = Arrays.asList( - new Person("aa", 12, "man", 1), - new Person("bb", 13, "woman", 2), - new Person("cc", 14, "man", 3), - new Person("dd", 15, "woman", 4), - new Person("ee", 16, "woman", 5), - new Person("ff", 17, "man", 6) + new Person("aa", 12, "man", 1), + new Person("bb", 13, "woman", 2), + new Person("cc", 14, "man", 3), + new Person("dd", 15, "woman", 4), + new Person("ee", 16, "woman", 5), + new Person("ff", 17, "man", 6) ); final Map genderMap = new HashMap<>(); @@ -946,12 +926,12 @@ public class CollUtilTest { @Test public void distinctByFunctionTest() { final List people = Arrays.asList( - new Person("aa", 12, "man", 1), - new Person("bb", 13, "woman", 2), - new Person("cc", 14, "man", 3), - new Person("dd", 15, "woman", 4), - new Person("ee", 16, "woman", 5), - new Person("ff", 17, "man", 6) + new Person("aa", 12, "man", 1), + new Person("bb", 13, "woman", 2), + new Person("cc", 14, "man", 3), + new Person("dd", 15, "woman", 4), + new Person("ee", 16, "woman", 5), + new Person("ff", 17, "man", 6) ); // 覆盖模式下ff覆盖了aa,ee覆盖了bb @@ -986,10 +966,10 @@ public class CollUtilTest { @Test public void mapBeanTest() { final List people = Arrays.asList( - new Person("aa", 12, "man", 1), - new Person("bb", 13, "woman", 2), - new Person("cc", 14, "man", 3), - new Person("dd", 15, "woman", 4) + new Person("aa", 12, "man", 1), + new Person("bb", 13, "woman", 2), + new Person("cc", 14, "man", 3), + new Person("dd", 15, "woman", 4) ); final List extract = CollUtil.map(people, Person::getName); @@ -1006,10 +986,10 @@ public class CollUtilTest { @Test public void transTest() { final List people = Arrays.asList( - new Person("aa", 12, "man", 1), - new Person("bb", 13, "woman", 2), - new Person("cc", 14, "man", 3), - new Person("dd", 15, "woman", 4) + new Person("aa", 12, "man", 1), + new Person("bb", 13, "woman", 2), + new Person("cc", 14, "man", 3), + new Person("dd", 15, "woman", 4) ); final Collection trans = CollUtil.trans(people, Person::getName); @@ -1046,8 +1026,8 @@ public class CollUtilTest { Assertions.assertNotNull(list); Assertions.assertEquals( - ListUtil.of(1, 2, 3, 4), - CollUtil.unionAll(ListUtil.of(1), ListUtil.of(2), ListUtil.of(3), ListUtil.of(4)) + ListUtil.of(1, 2, 3, 4), + CollUtil.unionAll(ListUtil.of(1), ListUtil.of(2), ListUtil.of(3), ListUtil.of(4)) ); } @@ -1083,14 +1063,14 @@ public class CollUtilTest { Assertions.assertFalse(CollUtil.addIfAbsent(null, "123")); Assertions.assertFalse(CollUtil.addIfAbsent(ListUtil.of("123"), "123")); Assertions.assertFalse(CollUtil.addIfAbsent(ListUtil.of(new Animal("jack", 20)), - new Animal("jack", 20))); + new Animal("jack", 20))); // 正常情况 Assertions.assertTrue(CollUtil.addIfAbsent(ListUtil.of("456"), "123")); Assertions.assertTrue(CollUtil.addIfAbsent(ListUtil.of(new Animal("jack", 20)), - new Dog("jack", 20))); + new Dog("jack", 20))); Assertions.assertTrue(CollUtil.addIfAbsent(ListUtil.of(new Animal("jack", 20)), - new Animal("tom", 20))); + new Animal("tom", 20))); } @Data @@ -1224,4 +1204,52 @@ public class CollUtilTest { final List pig = Arrays.asList(new Pig("pig1", 12), new Pig("pig2", 12)); Assertions.assertEquals(CollUtil.unionDistinct(dog, cat, pig).size(), 5); } + + + @Test + public void flatListTest1() { + List>> list = Arrays.asList(Arrays.asList(Arrays.asList("1", "2", "3"), Arrays.asList("5", "6", "7"))); + + List objects = CollUtil.flat(list); + + Assertions.assertArrayEquals(new String[]{"1", "2", "3", "5", "6", "7"}, objects.toArray()); + } + + + @Test + public void flatListTest2() { + List>> list = Arrays.asList( + Arrays.asList( + Arrays.asList("a"), + Arrays.asList("b", "c"), + Arrays.asList("d", "e", "f") + ), + Arrays.asList( + Arrays.asList("g", "h", "i"), + Arrays.asList("j", "k", "l") + ) + ); + List flat = CollUtil.flat(list); + Assertions.assertArrayEquals(new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}, flat.toArray()); + + } + + + @Test + void flatListTest3() { + List>> list = Arrays.asList( + Arrays.asList( + Arrays.asList("a"), + Arrays.asList("b", "c", null), + Arrays.asList("d", "e", "f") + ), + Arrays.asList( + Arrays.asList("g", "h", "i"), + Arrays.asList("j", "k", "l") + ) + ); + List flat = CollUtil.flat(list, false); + Assertions.assertArrayEquals(new String[]{"a", "b", "c", null, "d", "e", "f", "g", "h", "i", "j", "k", "l"}, flat.toArray()); + } + } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java index 60aa7b1fb..1c64f3299 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/stream/AbstractEnhancedWrappedStreamTest.java @@ -708,4 +708,23 @@ public class AbstractEnhancedWrappedStreamTest { private List children; } + + + @Test + void test() { + List>> list = Arrays.asList( + Arrays.asList( + Arrays.asList("a"), + Arrays.asList("b", "c"), + Arrays.asList("d", "e", "f") + ), + Arrays.asList( + Arrays.asList("g", "h", "i"), + Arrays.asList("j", "k", "l") + ) + ); + List r = EasyStream.of(list).flat().toList(); + Assertions.assertArrayEquals(new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}, r.toArray()); + } + }