diff --git a/CHANGELOG.md b/CHANGELOG.md index b4752f0f7..8b423aa08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * 【core 】 ListUtil增加page方法重载(pr#1761@Github) * 【crypto 】 增加ASN1Util * 【core 】 CsvConfig改为泛型形式 +* 【core 】 增加Partition ### 🐞Bug修复 diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java index ba44b21bd..5a6f5dbcc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -828,7 +828,7 @@ public class BeanUtil { * * @param bean Bean对象 * @param ignoreFiledNames 忽略检查的字段名 - * @return 是否为空,{@code true} - 空 / {@code false} - 非空 + * @return 是否为非空,{@code true} - 非空 / {@code false} - 空 * @since 5.0.7 */ public static boolean isNotEmpty(Object bean, String... ignoreFiledNames) { diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index 417f3a152..c0ac6536c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -366,7 +366,7 @@ public class CollUtil { */ public static Collection subtract(Collection coll1, Collection coll2) { Collection result = ObjectUtil.clone(coll1); - if(null == result){ + if (null == result) { result = CollUtil.create(coll1.getClass()); result.addAll(coll1); } @@ -1001,7 +1001,7 @@ public class CollUtil { } catch (Exception e) { // 无法创建当前类型的对象,尝试创建父类型对象 final Class superclass = collectionType.getSuperclass(); - if(null != superclass && collectionType != superclass){ + if (null != superclass && collectionType != superclass) { return create(superclass); } throw new UtilException(e); @@ -1028,20 +1028,21 @@ public class CollUtil { } /** - * 截取集合的部分 + * 截取列表的部分 * * @param 集合元素类型 * @param list 被截取的数组 * @param start 开始位置(包含) * @param end 结束位置(不包含) * @return 截取后的数组,当开始位置超过最大时,返回空的List + * @see ListUtil#sub(List, int, int) */ public static List sub(List list, int start, int end) { return ListUtil.sub(list, start, end); } /** - * 截取集合的部分 + * 截取列表的部分 * * @param 集合元素类型 * @param list 被截取的数组 @@ -1050,6 +1051,7 @@ public class CollUtil { * @param step 步进 * @return 截取后的数组,当开始位置超过最大时,返回空的List * @since 4.0.6 + * @see ListUtil#sub(List, int, int, int) */ public static List sub(List list, int start, int end, int step) { return ListUtil.sub(list, start, end, step); @@ -1072,19 +1074,20 @@ public class CollUtil { * 截取集合的部分 * * @param 集合元素类型 - * @param list 被截取的数组 + * @param collection 被截取的数组 * @param start 开始位置(包含) * @param end 结束位置(不包含) * @param step 步进 * @return 截取后的数组,当开始位置超过最大时,返回空集合 * @since 4.0.6 */ - public static List sub(Collection list, int start, int end, int step) { - if (list == null || list.isEmpty()) { + public static List sub(Collection collection, int start, int end, int step) { + if (isEmpty(collection)) { return ListUtil.empty(); } - return sub(new ArrayList<>(list), start, end, step); + final List list = collection instanceof List ? (List)collection : ListUtil.toList(collection); + return sub(list, start, end, step); } /** @@ -1099,9 +1102,11 @@ public class CollUtil { * @param size 每个段的长度 * @return 分段列表 * @since 5.4.5 + * @deprecated 请使用 {@link ListUtil#partition(List, int)} */ + @Deprecated public static List> splitList(List list, int size) { - return ListUtil.split(list, size); + return ListUtil.partition(list, size); } /** @@ -1150,7 +1155,7 @@ public class CollUtil { } Collection collection2 = ObjectUtil.clone(collection); - if(null == collection2){ + if (null == collection2) { // 不支持clone collection2 = create(collection.getClass()); } @@ -1189,7 +1194,7 @@ public class CollUtil { * @since 3.1.0 */ public static Collection filterNew(Collection collection, Filter filter) { - if(null == collection || null == filter){ + if (null == collection || null == filter) { return collection; } return edit(collection, t -> filter.accept(t) ? t : null); diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index c08f15ad3..8a368cd40 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -2,7 +2,6 @@ package cn.hutool.core.collection; import cn.hutool.core.comparator.PinyinComparator; import cn.hutool.core.comparator.PropertyComparator; -import cn.hutool.core.lang.Console; import cn.hutool.core.lang.Matcher; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; @@ -16,6 +15,7 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.RandomAccess; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; @@ -521,7 +521,8 @@ public class ListUtil { } /** - * 对集合按照指定长度分段,每一个段为单独的集合,返回这个集合的列表 + * 通过传入分区长度,将指定列表分区为不同的块,每块区域的长度相同(最后一块可能小于长度)
+ * 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。 * *

* 需要特别注意的是,此方法调用{@link List#subList(int, int)}切分List, @@ -534,20 +535,32 @@ public class ListUtil { * @return 分段列表 * @since 5.4.5 */ - public static List> split(List list, int size) { + public static List> partition(List list, int size) { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } - final int listSize = list.size(); - final List> result = new ArrayList<>(listSize / size + 1); - int offset = 0; - for (int toIdx = size; toIdx <= listSize; offset = toIdx, toIdx += size) { - result.add(list.subList(offset, toIdx)); - } - if (offset < listSize) { - result.add(list.subList(offset, listSize)); - } - return result; + return (list instanceof RandomAccess) + ? new RandomAccessPartition<>(list, size) + : new Partition<>(list, size); + } + + /** + * 对集合按照指定长度分段,每一个段为单独的集合,返回这个集合的列表 + * + *

+ * 需要特别注意的是,此方法调用{@link List#subList(int, int)}切分List, + * 此方法返回的是原List的视图,也就是说原List有变更,切分后的结果也会变更。 + *

+ * + * @param 集合元素类型 + * @param list 列表 + * @param size 每个段的长度 + * @return 分段列表 + * @since 5.4.5 + * @see #partition(List, int) + */ + public static List> split(List list, int size) { + return partition(list, size); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/Partition.java b/hutool-core/src/main/java/cn/hutool/core/collection/Partition.java new file mode 100644 index 000000000..6ac22812f --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/collection/Partition.java @@ -0,0 +1,53 @@ +package cn.hutool.core.collection; + +import java.util.AbstractList; +import java.util.List; + +/** + * 列表分区或分段
+ * 通过传入分区长度,将指定列表分区为不同的块,每块区域的长度相同(最后一块可能小于长度)
+ * 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。 + * 参考:Guava的Lists#Partition + * + * @param 元素类型 + * @author looly, guava + * @since 5.7.10 + */ +public class Partition extends AbstractList> { + final List list; + final int size; + + /** + * 列表分区 + * + * @param list 被分区的列表 + * @param size 每个分区的长度 + */ + public Partition(List list, int size) { + this.list = list; + this.size = size; + } + + @Override + public List get(int index) { + int start = index * size; + int end = Math.min(start + size, list.size()); + return list.subList(start, end); + } + + @Override + public int size() { + // 此处采用动态计算,以应对list变化 + final int total = list.size(); + int length = total / size; + if(total % length > 0){ + length += 1; + } + return length; + } + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/RandomAccessPartition.java b/hutool-core/src/main/java/cn/hutool/core/collection/RandomAccessPartition.java new file mode 100644 index 000000000..d6cb3aad2 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/collection/RandomAccessPartition.java @@ -0,0 +1,27 @@ +package cn.hutool.core.collection; + +import java.util.List; +import java.util.RandomAccess; + +/** + * 列表分区或分段(可随机访问列表)
+ * 通过传入分区长度,将指定列表分区为不同的块,每块区域的长度相同(最后一块可能小于长度)
+ * 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。 + * 参考:Guava的Lists#RandomAccessPartition + * + * @param 元素类型 + * @author looly, guava + * @since 5.7.10 + */ +public class RandomAccessPartition extends Partition implements RandomAccess { + + /** + * 构造 + * + * @param list 被分区的列表,必须实现{@link RandomAccess} + * @param size 每个分区的长度 + */ + public RandomAccessPartition(List list, int size) { + super(list, size); + } +}