mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add method
This commit is contained in:
parent
8be645e9fb
commit
40828f69d1
@ -15,9 +15,10 @@
|
||||
* 【core 】 XmlUtil增加append重载(issue#I466Q0@Gitee)
|
||||
* 【poi 】 增加EscapeStrCellSetter(issue#I466ZZ@Gitee)
|
||||
* 【poi 】 ExcelBase增加renameSheet、cloneSheet(issue#I466ZZ@Gitee)
|
||||
* 【core 】 修复MapUtil.sort比较器不一致返回原map的问题(issue#I46AQJ@Gitee)
|
||||
* 【core 】 ListUtil增加splitAvg方法(pr#397@Gitee)
|
||||
|
||||
### 🐞Bug修复
|
||||
* 【core 】 修复MapUtil.sort比较器不一致返回原map的问题(issue#I46AQJ@Gitee)
|
||||
* 【core 】 修复JSONSupport默认循环引用导致的问题(issue#1779@Github)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
@ -0,0 +1,57 @@
|
||||
package cn.hutool.core.collection;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 列表分区或分段<br>
|
||||
* 通过传入分区个数,将指定列表分区为不同的块,每块区域的长度均匀分布(个数差不超过1)<br>
|
||||
* <pre>
|
||||
* [1,2,3,4] -》 [1,2], [3, 4]
|
||||
* [1,2,3,4] -》 [1,2], [3], [4]
|
||||
* [1,2,3,4] -》 [1], [2], [3], [4]
|
||||
* [1,2,3,4] -》 [1], [2], [3], [4], []
|
||||
* </pre>
|
||||
* 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @author looly
|
||||
* @since 5.7.10
|
||||
*/
|
||||
public class AvgPartition<T> extends Partition<T> {
|
||||
|
||||
final int limit;
|
||||
// 平均分完后剩余的个数,平均放在前remainder个分区中
|
||||
final int remainder;
|
||||
|
||||
/**
|
||||
* 列表分区
|
||||
*
|
||||
* @param list 被分区的列表
|
||||
* @param limit 分区个数
|
||||
*/
|
||||
public AvgPartition(List<T> list, int limit) {
|
||||
super(list, list.size() / (limit <= 0 ? 1 : limit));
|
||||
Assert.isTrue(limit > 0, "Partition limit must be > 0");
|
||||
this.limit = limit;
|
||||
this.remainder = list.size() % limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> get(int index) {
|
||||
// 当limit个数超过list的size时,size为0,此时每个分区分1个元素,直到remainder个分配完,剩余分区为[]
|
||||
int start = index * size + Math.min(index, remainder);
|
||||
int end = start + size;
|
||||
if (index + 1 <= remainder) {
|
||||
// 将remainder个元素平均分布在前面,每个分区分1个
|
||||
end += 1;
|
||||
}
|
||||
return list.subList(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return limit;
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.PageUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@ -538,7 +537,7 @@ public class ListUtil {
|
||||
*/
|
||||
public static <T> List<List<T>> partition(List<T> list, int size) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
return empty();
|
||||
}
|
||||
|
||||
return (list instanceof RandomAccess)
|
||||
@ -558,8 +557,8 @@ public class ListUtil {
|
||||
* @param list 列表
|
||||
* @param size 每个段的长度
|
||||
* @return 分段列表
|
||||
* @since 5.4.5
|
||||
* @see #partition(List, int)
|
||||
* @since 5.4.5
|
||||
*/
|
||||
public static <T> List<List<T>> split(List<T> list, int size) {
|
||||
return partition(list, size);
|
||||
@ -568,40 +567,27 @@ public class ListUtil {
|
||||
/**
|
||||
* 将集合平均分成多个list,返回这个集合的列表
|
||||
* <p>例:</p>
|
||||
* <blockquote><pre>
|
||||
* ListUtil.splitAvg(null, 3); // [[], [], []]
|
||||
* <pre>
|
||||
* ListUtil.splitAvg(null, 3); // []
|
||||
* ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 2); // [[1, 2], [3, 4]]
|
||||
* ListUtil.splitAvg(Arrays.asList(1, 2, 3), 5); // [[1], [2], [3], [], []]
|
||||
* ListUtil.splitAvg(Arrays.asList(1, 2, 3), 2); // [[1, 2], [3]]
|
||||
* </pre></blockquote>
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> 集合元素类型
|
||||
* @param list 集合
|
||||
* @param limit 要均分成几个list
|
||||
* @return 分段列表
|
||||
* @author lileming
|
||||
* @since 5.7.10
|
||||
*/
|
||||
public static <T> List<List<T>> splitAvg(List<T> list, int limit) {
|
||||
final List<List<T>> result = new ArrayList<>();
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
for (int i = 0; i < limit; i++) {
|
||||
result.add(new ArrayList<>());
|
||||
return empty();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int remainder = list.size() % limit;
|
||||
int number = list.size() / limit;
|
||||
int offset = 0;
|
||||
for (int i = 0; i < limit; i++) {
|
||||
List<T> value;
|
||||
if (remainder > 0) {
|
||||
value = list.subList(i * number + offset, (i + 1) * number + offset + 1);
|
||||
remainder--;
|
||||
offset++;
|
||||
} else {
|
||||
value = list.subList(i * number + offset, (i + 1) * number + offset);
|
||||
}
|
||||
result.add(value);
|
||||
}
|
||||
return result;
|
||||
|
||||
return (list instanceof RandomAccess)
|
||||
? new RandomAccessAvgPartition<>(list, limit)
|
||||
: new AvgPartition<>(list, limit);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import java.util.List;
|
||||
* @since 5.7.10
|
||||
*/
|
||||
public class Partition<T> extends AbstractList<List<T>> {
|
||||
|
||||
final List<T> list;
|
||||
final int size;
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
package cn.hutool.core.collection;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.RandomAccess;
|
||||
|
||||
/**
|
||||
* 列表分区或分段(可随机访问列表)<br>
|
||||
* 通过传入分区个数,将指定列表分区为不同的块,每块区域的长度均匀分布(个数差不超过1)<br>
|
||||
* <pre>
|
||||
* [1,2,3,4] -》 [1,2], [3, 4]
|
||||
* [1,2,3,4] -》 [1,2], [3], [4]
|
||||
* [1,2,3,4] -》 [1], [2], [3], [4]
|
||||
* [1,2,3,4] -》 [1], [2], [3], [4], []
|
||||
* </pre>
|
||||
* 分区是在原List的基础上进行的,返回的分区是不可变的抽象列表,原列表元素变更,分区中元素也会变更。
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @author looly
|
||||
* @since 5.7.10
|
||||
*/
|
||||
public class RandomAccessAvgPartition<T> extends AvgPartition<T> implements RandomAccess {
|
||||
|
||||
/**
|
||||
* 列表分区
|
||||
*
|
||||
* @param list 被分区的列表
|
||||
* @param limit 分区个数
|
||||
*/
|
||||
public RandomAccessAvgPartition(List<T> list, int limit) {
|
||||
super(list, limit);
|
||||
}
|
||||
}
|
@ -9,13 +9,14 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ListUtilTest {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void split() {
|
||||
public void splitBenchTest() {
|
||||
List<String> list = new ArrayList<>();
|
||||
CollUtil.padRight(list, RandomUtil.randomInt(1000_0000, 1_0000_0000), "test");
|
||||
|
||||
@ -37,6 +38,32 @@ public class ListUtilTest {
|
||||
Console.log(stopWatch.prettyPrint());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitAvgTest(){
|
||||
List<List<Object>> lists = ListUtil.splitAvg(null, 3);
|
||||
Assert.assertEquals(ListUtil.empty(), lists);
|
||||
|
||||
lists = ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 1);
|
||||
Assert.assertEquals("[[1, 2, 3, 4]]", lists.toString());
|
||||
lists = ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 2);
|
||||
Assert.assertEquals("[[1, 2], [3, 4]]", lists.toString());
|
||||
lists = ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 3);
|
||||
Assert.assertEquals("[[1, 2], [3], [4]]", lists.toString());
|
||||
lists = ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 4);
|
||||
Assert.assertEquals("[[1], [2], [3], [4]]", lists.toString());
|
||||
|
||||
lists = ListUtil.splitAvg(Arrays.asList(1, 2, 3), 5);
|
||||
Assert.assertEquals("[[1], [2], [3], [], []]", lists.toString());
|
||||
lists = ListUtil.splitAvg(Arrays.asList(1, 2, 3), 2);
|
||||
Assert.assertEquals("[[1, 2], [3]]", lists.toString());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void splitAvgNotZero(){
|
||||
// limit不能小于等于0
|
||||
ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void editTest(){
|
||||
List<String> a = ListUtil.toLinkedList("1", "2", "3");
|
||||
|
Loading…
x
Reference in New Issue
Block a user