Lists.partion踩的坑和自己写的工具类

659 阅读3分钟

踩坑场景

某个业务场景,需要用到多线程,设计上根据店铺做分片,使用了Lists.partion做切分。本意上是要切分成n个子列表,但是Lists.partion作用不是切分成n个列表,而是切分成m个列表,每个列表元素为n个。导致本来想4个线程执行,变成了几十个线程,无知坑了自己。

partion方法定义

 /**
   * Returns consecutive {@linkplain List#subList(int, int) sublists} of a list,
   * each of the same size (the final list may be smaller). For example,
   * partitioning a list containing {@code [a, b, c, d, e]} with a partition
   * size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing
   * two inner lists of three and two elements, all in the original order.
   *
   * <p>The outer list is unmodifiable, but reflects the latest state of the
   * source list. The inner lists are sublist views of the original list,
   * produced on demand using {@link List#subList(int, int)}, and are subject
   * to all the usual caveats about modification as explained in that API.
   *
   * @param list the list to return consecutive sublists of
   * @param size the desired size of each sublist (the last may be
   *     smaller)
   * @return a list of consecutive sublists
   * @throws IllegalArgumentException if {@code partitionSize} is nonpositive
   */
  public static <T> List<List<T>> partition(List<T> list, int size) {
    checkNotNull(list);
    checkArgument(size > 0);
    return (list instanceof RandomAccess)
        ? new RandomAccessPartition<>(list, size)
        : new Partition<>(list, size);
  }

自己写的工具类

为了实现切分成n个子列表,自己写了个工具类,代码和单测如下

工具类代码

package com.test;

import com.google.common.collect.Lists;
import lombok.experimental.UtilityClass;
import org.apache.commons.collections4.CollectionUtils;

import java.util.Collections;
import java.util.List;

/**
 * 列表工具
 * @author 
 * @date 2021/12/22
 */
@UtilityClass
public class CubeListUtil {


    /**
     * 把列表切分成n个子列表
     * 不是均分的,最后一个子列表会兜底剩余的所有未分配的元素
     *
     * @param list 待拆分列表
     * @param num 拆分子列表数量
     * @param <T> 类型
     * @return 子列表
     */
    public <T> List<List<T>> subList(List<T> list, int num) {
        if(CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        if(num <= 1) {
            return Collections.singletonList(list);
        }
        // 拆分数量大于列表数量,则拆分数量调整为列表数量
        if(num > list.size()) {
            num = list.size();
        }
        int start = 0;
        int eachSize = list.size() / num;
        List<List<T>> subLists = Lists.newArrayListWithCapacity(num);
        for (int i = 1; i <= num; i++) {
            int end = i == num ? list.size() : start + eachSize;
            subLists.add(list.subList(start, end));
            start += eachSize;
        }
        return subLists;
    }

    /**
     * 把列表平均切分成n个子列表
     * @param list 待拆分列表
     * @param num 拆分子列表数量
     * @param <T> 类型
     * @return 子列表
     */
    public <T> List<List<T>> meanSubList(List<T> list, int num) {
        if(CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        if(num <= 1) {
            return Collections.singletonList(list);
        }
        // 拆分数量大于列表数量,则拆分数量调整为列表数量
        if(num > list.size()) {
            num = list.size();
        }
        int start = 0;
        int eachSize = list.size() / num;
        int rem = list.size() % num;

        List<List<T>> subLists = Lists.newArrayListWithCapacity(num);
        for (int i = 1; i <= num; i++) {
            // 如果有余数,则增加1个
            int extra = rem-- <= 0 ? 0 : 1;
            int end = i == num ? list.size() : start + eachSize + extra;
            subLists.add(list.subList(start, end));
            start += eachSize + extra;
        }
        return subLists;
    }
}

单测

package com.test;

import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;

/**
 * 列表工具单测
 *
 * @author 
 * @date 2021/12/22
 */
public class CubeListUtilTest {

    private static final List<Integer> LIST = Lists.newArrayList(1, 2, 3, 4, 5);

    @Test
    public void subList_list5_num1() {
        List<List<Integer>> lists = CubeListUtil.subList(LIST, 1);

        Assert.assertEquals("列表数量不对", 1, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1, 2, 3, 4, 5), lists.get(0)));
    }

    /**
     * 5 / 2 = 2
     * [1,2,3,4,5] -> [[1,2],[3,4,5]]
     */
    @Test
    public void subList_list5_num2() {
        List<List<Integer>> lists = CubeListUtil.subList(LIST, 2);

        Assert.assertEquals("列表数量不对", 2, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1, 2), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3, 4, 5), lists.get(1)));
    }

    /**
     * 5 / 3 = 1
     * [1,2,3,4,5] -> [[1],[2],[3,4,5]]
     */
    @Test
    public void subList_list5_num3() {
        List<List<Integer>> lists = CubeListUtil.subList(LIST, 3);

        Assert.assertEquals("列表数量不对", 3, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(2), lists.get(1)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3,4,5), lists.get(2)));
    }

    /**
     * 5 / 4 = 1
     * [1,2,3,4,5] -> [[1],[2],[3],[4,5]]
     */
    @Test
    public void subList_list5_num4() {
        List<List<Integer>> lists = CubeListUtil.subList(LIST, 4);

        Assert.assertEquals("列表数量不对", 4, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(2), lists.get(1)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3), lists.get(2)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(4, 5), lists.get(3)));
    }

    @Test
    public void subList_list5_num5() {
        List<List<Integer>> lists = CubeListUtil.subList(LIST, 5);

        Assert.assertEquals("列表数量不对", 5, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(2), lists.get(1)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3), lists.get(2)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(4), lists.get(3)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(5), lists.get(4)));

    }

    @Test
    public void subList_list5_num6() {
        List<List<Integer>> lists = CubeListUtil.subList(LIST, 6);

        Assert.assertEquals("列表数量不对", 5, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(2), lists.get(1)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3), lists.get(2)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(4), lists.get(3)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(5), lists.get(4)));
    }



    @Test
    public void meanSubList_list5_num0() {
        List<List<Integer>> lists = CubeListUtil.meanSubList(LIST, 0);

        Assert.assertEquals("列表数量不对", 1, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1, 2, 3, 4, 5), lists.get(0)));
    }

    @Test
    public void meanSubList_list5_num1() {
        List<List<Integer>> lists = CubeListUtil.meanSubList(LIST, 1);

        Assert.assertEquals("列表数量不对", 1, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1, 2, 3, 4, 5), lists.get(0)));
    }

    /**
     * [1,2,3,4,5] -> [[1,2,3],[4,5]]
     */
    @Test
    public void meanSubList_list5_num2() {
        List<List<Integer>> lists = CubeListUtil.meanSubList(LIST, 2);

        Assert.assertEquals("列表数量不对", 2, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1, 2, 3), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(4, 5), lists.get(1)));

    }

    /**
     * 5 / 3 = 1 ; 5 % 3 = 2
     * [1,2,3,4,5] -> [[1,2],[3,4],[5]]
     */
    @Test
    public void meanSubList_list5_num3() {
        List<List<Integer>> lists = CubeListUtil.meanSubList(LIST, 3);

        Assert.assertEquals("列表数量不对", 3, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1, 2), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3, 4), lists.get(1)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(5), lists.get(2)));
    }

    /**
     * 5 / 4 = 1 ; 5 % 4 = 1
     * [1,2,3,4,5] -> [[1,2],[3],[4],[5]]
     */
    @Test
    public void meanSubList_list5_num4() {
        List<List<Integer>> lists = CubeListUtil.meanSubList(LIST, 4);

        Assert.assertEquals("列表数量不对", 4, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1, 2), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3), lists.get(1)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(4), lists.get(2)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(5), lists.get(3)));
    }

    @Test
    public void meanSubList_list5_num6() {
        List<List<Integer>> lists = CubeListUtil.meanSubList(LIST, 6);

        Assert.assertEquals("列表数量不对", 5, lists.size());

        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(1), lists.get(0)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(2), lists.get(1)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3), lists.get(2)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(4), lists.get(3)));
        Assert.assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(5), lists.get(4)));

    }
}

其他

使用方法前应好好看注释文档