Java:如何将一个数组列表分割成多个小数组列表?

如何将一个数组列表(size=1000)拆分为多个相同大小(=10)的数组列表?

ArrayList<Integer> results;
493041 次浏览

我猜你遇到的问题是命名100个数组列表并填充它们。您可以创建一个数组列表数组,并使用循环填充每个数组列表。

最简单(也是最愚蠢的)的方法是这样的:

ArrayList results = new ArrayList(1000);
// populate results here
for (int i = 0; i < 1000; i++) {
results.add(i);
}
ArrayList[] resultGroups = new ArrayList[100];
// initialize all your small ArrayList groups
for (int i = 0; i < 100; i++) {
resultGroups[i] = new ArrayList();
}
// put your results into those arrays
for (int i = 0; i < 1000; i++) {
resultGroups[i/10].add(results.get(i));
}

你可以使用subList(int fromIndex, int toIndex)来获取原始列表的一部分视图。

来自API:

返回该列表中指定的fromIndex(包含)和toIndex(排除)之间部分的视图。(如果fromIndextoIndex相等,返回的列表为空。)返回的列表由该列表支持,因此返回列表中的非结构性更改会反映在该列表中,反之亦然。返回的列表支持该列表支持的所有可选列表操作。

例子:

List<Integer> numbers = new ArrayList<Integer>(
Arrays.asList(5,3,1,2,9,5,0,7)
);


List<Integer> head = numbers.subList(0, 4);
List<Integer> tail = numbers.subList(4, 8);
System.out.println(head); // prints "[5, 3, 1, 2]"
System.out.println(tail); // prints "[9, 5, 0, 7]"


Collections.sort(head);
System.out.println(numbers); // prints "[1, 2, 3, 5, 9, 5, 0, 7]"


tail.add(-1);
System.out.println(numbers); // prints "[1, 2, 3, 5, 9, 5, 0, 7, -1]"

如果你需要这些切碎的列表不是一个视图,那么只需从subList中创建一个新的List。下面是一个把这些东西放在一起的例子:

// chops a list into non-view sublists of length L
static <T> List<List<T>> chopped(List<T> list, final int L) {
List<List<T>> parts = new ArrayList<List<T>>();
final int N = list.size();
for (int i = 0; i < N; i += L) {
parts.add(new ArrayList<T>(
list.subList(i, Math.min(N, i + L)))
);
}
return parts;
}




List<Integer> numbers = Collections.unmodifiableList(
Arrays.asList(5,3,1,2,9,5,0,7)
);
List<List<Integer>> parts = chopped(numbers, 3);
System.out.println(parts); // prints "[[5, 3, 1], [2, 9, 5], [0, 7]]"
parts.get(0).add(-1);
System.out.println(parts); // prints "[[5, 3, 1, -1], [2, 9, 5], [0, 7]]"
System.out.println(numbers); // prints "[5, 3, 1, 2, 9, 5, 0, 7]" (unmodified!)

这里讨论了一个类似的问题,Java:把一个列表分成两个子列表?

主要可以使用子列表。更多细节:子表

返回该列表中frommindex(包含)和toIndex(不包含)之间部分的视图。(如果fromIndex和toIndex相等,返回的列表为空。)返回的列表受此列表支持,因此返回列表中的更改将反映在此列表中,反之亦然。返回的列表支持该列表支持的所有可选列表操作…

你可以将番石榴库添加到你的项目中,并使用Lists.partition方法。

List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);

聚基因润滑剂提供的答案是根据给定的大小拆分数组。我正在寻找将数组分割成给定数量的部分的代码。以下是我对代码所做的修改:

public static <T>List<List<T>> chopIntoParts( final List<T> ls, final int iParts )
{
final List<List<T>> lsParts = new ArrayList<List<T>>();
final int iChunkSize = ls.size() / iParts;
int iLeftOver = ls.size() % iParts;
int iTake = iChunkSize;


for( int i = 0, iT = ls.size(); i < iT; i += iTake )
{
if( iLeftOver > 0 )
{
iLeftOver--;


iTake = iChunkSize + 1;
}
else
{
iTake = iChunkSize;
}


lsParts.add( new ArrayList<T>( ls.subList( i, Math.min( iT, i + iTake ) ) ) );
}


return lsParts;
}

希望它能帮助到别人。

你也可以使用FunctionalJava库——Listpartition方法。这个库有自己的集合类型,你可以将它们来回转换为java集合。

import fj.data.List;


java.util.List<String> javaList = Arrays.asList("a", "b", "c", "d" );


List<String> fList = Java.<String>Collection_List().f(javaList);


List<List<String> partitions = fList.partition(2);

Apache Commons Collections 4ListUtils类中有一个分区方法。下面是它的工作原理:

import org.apache.commons.collections4.ListUtils;
...


int targetSize = 100;
List<Integer> largeList = ...
List<List<Integer>> output = ListUtils.partition(largeList, targetSize);

创建一个新列表,并使用addAll()方法添加源列表的子列表视图来创建一个新的子列表

List<T> newList = new ArrayList<T>();
newList.addAll(sourceList.subList(startIndex, endIndex));

如果你不想导入apache Commons库,试试下面这段简单的代码:

final static int MAX_ELEMENT = 20;


public static void main(final String[] args) {


final List<String> list = new ArrayList<String>();


for (int i = 1; i <= 161; i++) {
list.add(String.valueOf(i));
System.out.print("," + String.valueOf(i));
}
System.out.println("");
System.out.println("### >>> ");
final List<List<String>> result = splitList(list, MAX_ELEMENT);


for (final List<String> entry : result) {
System.out.println("------------------------");
for (final String elm : entry) {
System.out.println(elm);
}
System.out.println("------------------------");
}


}


private static List<List<String>> splitList(final List<String> list, final int maxElement) {


final List<List<String>> result = new ArrayList<List<String>>();


final int div = list.size() / maxElement;


System.out.println(div);


for (int i = 0; i <= div; i++) {


final int startIndex = i * maxElement;


if (startIndex >= list.size()) {
return result;
}


final int endIndex = (i + 1) * maxElement;


if (endIndex < list.size()) {
result.add(list.subList(startIndex, endIndex));
} else {
result.add(list.subList(startIndex, list.size()));
}


}


return result;
}

这对我很有用

/**
* Returns List of the List argument passed to this function with size = chunkSize
*
* @param largeList input list to be portioned
* @param chunkSize maximum size of each partition
* @param <T> Generic type of the List
* @return A list of Lists which is portioned from the original list
*/
public static  <T> List<List<T>> chunkList(List<T> list, int chunkSize) {
if (chunkSize <= 0) {
throw new IllegalArgumentException("Invalid chunk size: " + chunkSize);
}
List<List<T>> chunkList = new ArrayList<>(list.size() / chunkSize);
for (int i = 0; i < list.size(); i += chunkSize) {
chunkList.add(list.subList(i, i + chunkSize >= list.size() ? list.size()-1 : i + chunkSize));
}
return chunkList;
}

例如:

List<Integer> stringList = new ArrayList<>();
stringList.add(0);
stringList.add(1);
stringList.add(2);
stringList.add(3);
stringList.add(4);
stringList.add(5);
stringList.add(6);
stringList.add(7);
stringList.add(8);
stringList.add(9);


List<List<Integer>> chunkList = getChunkList1(stringList, 2);
import org.apache.commons.collections4.ListUtils;
ArrayList<Integer> mainList = .............;
List<List<Integer>> multipleLists = ListUtils.partition(mainList,100);
int i=1;
for (List<Integer> indexedList : multipleLists){
System.out.println("Values in List "+i);
for (Integer value : indexedList)
System.out.println(value);
i++;
}

您需要知道您划分列表的块大小。假设你有一个108 entries的列表,你需要一个25的块大小。这样你就会得到5 lists:

  • 4 .有25 entries每个;
  • 1(第五个)有8 elements

代码:

public static void main(String[] args) {


List<Integer> list = new ArrayList<Integer>();
for (int i=0; i<108; i++){
list.add(i);
}
int size= list.size();
int j=0;
List< List<Integer> > splittedList = new ArrayList<List<Integer>>()  ;
List<Integer> tempList = new ArrayList<Integer>();
for(j=0;j<size;j++){
tempList.add(list.get(j));
if((j+1)%25==0){
// chunk of 25 created and clearing tempList
splittedList.add(tempList);
tempList = null;
//intializing it again for new chunk
tempList = new ArrayList<Integer>();
}
}
if(size%25!=0){
//adding the remaining enteries
splittedList.add(tempList);
}
for (int k=0;k<splittedList.size(); k++){
//(k+1) because we started from k=0
System.out.println("Chunk number: "+(k+1)+" has elements = "+splittedList.get(k).size());
}
}

Java 8

我们可以根据大小或条件拆分列表。

static Collection<List<Integer>> partitionIntegerListBasedOnSize(List<Integer> inputList, int size) {
return inputList.stream()
.collect(Collectors.groupingBy(s -> (s-1)/size))
.values();
}
static <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int size) {
final AtomicInteger counter = new AtomicInteger(0);
return inputList.stream()
.collect(Collectors.groupingBy(s -> counter.getAndIncrement()/size))
.values();
}
static <T> Collection<List<T>> partitionBasedOnCondition(List<T> inputList, Predicate<T> condition) {
return inputList.stream().collect(Collectors.partitioningBy(s-> (condition.test(s)))).values();
}

然后我们可以把它们用作:

final List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println(partitionIntegerListBasedOnSize(list, 4));  // [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
System.out.println(partitionBasedOnSize(list, 4));  // [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
System.out.println(partitionBasedOnSize(list, 3));  // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
System.out.println(partitionBasedOnCondition(list, i -> i<6));  // [[6, 7, 8, 9, 10], [1, 2, 3, 4, 5]]

只是要明确一点,这还需要更多的测试…

public class Splitter {


public static <T> List<List<T>> splitList(List<T> listTobeSplit, int size) {
List<List<T>> sublists= new LinkedList<>();
if(listTobeSplit.size()>size) {
int counter=0;
boolean lastListadded=false;


List<T> subList=new LinkedList<>();


for(T t: listTobeSplit) {
if (counter==0) {
subList =new LinkedList<>();
subList.add(t);
counter++;
lastListadded=false;
}
else if(counter>0 && counter<size-1) {
subList.add(t);
counter++;
}
else {
lastListadded=true;
subList.add(t);
sublists.add(subList);
counter=0;
}
}
if(lastListadded==false)
sublists.add(subList);
}
else {
sublists.add(listTobeSplit);
}
log.debug("sublists: "+sublists);
return sublists;
}
}
private ArrayList<List<String>> chunkArrayList(ArrayList<String> arrayToChunk, int chunkSize) {
ArrayList<List<String>> chunkList = new ArrayList<>();
int guide = arrayToChunk.size();
int index = 0;
int tale = chunkSize;
while (tale < arrayToChunk.size()){
chunkList.add(arrayToChunk.subList(index, tale));
guide = guide - chunkSize;
index = index + chunkSize;
tale = tale + chunkSize;
}
if (guide >0) {
chunkList.add(arrayToChunk.subList(index, index + guide));
}
Log.i("Chunked Array: " , chunkList.toString());
return chunkList;
}

例子

    ArrayList<String> test = new ArrayList<>();
for (int i=1; i<=1000; i++){
test.add(String.valueOf(i));
}


chunkArrayList(test,10);

输出

分块:[[1,2,3,4,5,6,7,8,9,10),(11、12、13、14、15、16、17、18、19、20],[21日,22日,23日,24日,25日,26日,27日,28日,29日,30日],[第三十一条、第三十二条、第三十三,34岁,35岁,36岁,37岁,38岁,39岁,40],[41、42、43、44、45、46岁,47岁,48岁,49岁,50],[51岁,52岁,53岁,54岁,55岁,56岁,57岁的58岁的59岁60],[61,62,63,64,65,66,67,68,69,70],[71,72,73,74,75,76,77,78,79,80],[81,82,83,84,85,86,87,88,89,90],[91,92,93,94,95,96,97,98,99,100 ], .........

你会在日志里看到的

你可以在Eclipse集合中使用chunk方法:

ArrayList<Integer> list = new ArrayList<>(Interval.oneTo(1000));
RichIterable<RichIterable<Integer>> chunks = Iterate.chunk(list, 10);
Verify.assertSize(100, chunks);

chunk方法的一些例子也包含在这个DZone文章中。

注意:我是Eclipse Collections的提交者。

    **Divide a list to lists of n size**


import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;


public final class PartitionUtil<T> extends AbstractList<List<T>> {


private final List<T> list;
private final int chunkSize;


private PartitionUtil(List<T> list, int chunkSize) {
this.list = new ArrayList<>(list);
this.chunkSize = chunkSize;
}


public static <T> PartitionUtil<T> ofSize(List<T> list, int chunkSize) {
return new PartitionUtil<>(list, chunkSize);
}


@Override
public List<T> get(int index) {
int start = index * chunkSize;
int end = Math.min(start + chunkSize, list.size());


if (start > end) {
throw new IndexOutOfBoundsException("Index " + index + " is out of the list range <0," + (size() - 1) + ">");
}


return new ArrayList<>(list.subList(start, end));
}


@Override
public int size() {
return (int) Math.ceil((double) list.size() / (double) chunkSize);
}
}










Function call :
List<List<String>> containerNumChunks = PartitionUtil.ofSize(list, 999)

更多详细信息:https://e.printstacktrace.blog/divide-a-list-to-lists-of-n-size-in-Java-8/

让我们假设您想要将列表分割为多个块的类作为库类。

所以让我们说这个类被称为“shared”,in应该是final,以确保它不会被扩展。

   import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public final class Shared {
List<Integer> input;
int portion;


public Shared(int portion, Integer... input) {
this.setPortion(portion);
this.setInput(input);
}


public List<List<Integer>> listToChunks() {
List<List<Integer>> result = new ArrayList<List<Integer>>();
int size = this.size();
int startAt = 0;
int endAt = this.portion;


while (endAt <= size) {


result.add(this.input.subList(startAt, endAt));
startAt = endAt;
endAt = (size - endAt < this.portion && size - endAt > 0) ? (this.size()) : (endAt + this.portion);
}


return result;
}


public int size() {
return this.input.size();
}


public void setInput(Integer... input) {
if (input != null && input.length > 0)
this.input = Arrays.asList(input);
else
System.out.println("Error 001 : please enter a valid array of integers.");
}


public void setPortion(int portion) {
if (portion > 0)
this.portion = portion;
else
System.out.println("Error 002 : please enter a valid positive number.");
}
}

接下来,让我们尝试从另一个持有公共静态void main(String…args)

public class exercise {


public static void main(String[] args) {
Integer[] numbers = {1, 2, 3, 4, 5, 6, 7};
int portion = 2;
Shared share = new Shared(portion, numbers);
System.out.println(share.listToChunks());
}
}

现在,如果您输入一个整数数组[1,2,3,4,5,6,7],分区为2。 结果将是[[1、2],[3,4],[5,6],[7]]< / p >

使用StreamEx库,你可以使用StreamEx.ofSubLists(List<T> source, int length)方法:

返回一个新的StreamEx,它由给定源列表的不重叠子列表组成,具有指定的长度(最后一个子列表可能更短)。

// Assuming you don't actually care that the lists are of type ArrayList
List<List<Integer>> sublists = StreamEx.ofSubLists(result, 10).toList();


// If you actually want them to be of type ArrayList, per your question
List<List<Integer>> sublists = StreamEx.ofSubLists(result, 10).toCollection(ArrayList::new);

Java8流,一个表达式,没有其他库:

List<String> input = ...
int partitionSize = ...


Collection<List<String>> partitionedList = IntStream.range(0, input.size())
.boxed()
.collect(Collectors.groupingBy(partition -> (partition / partitionSize), Collectors.mapping(elementIndex -> input.get(elementIndex), Collectors.toList())))
.values();

测试:

List<String> input = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h" ,"i");

partitionSize = 1 ->[[a], [b], [c], [d], [e], [f], [g], [h], [I]]

partitionSize = 2 ->[a, b], [c, d], [e, f], [g, h], [I]]

partitionSize = 3 ->[a, b, c], [d, e, f], [g, h, I]]

partitionSize = 7 ->[[a, b, c, d, e, f, g], [h, I]]

partitionSize = 100 ->[[a, b, c, d, e, f, g, h, i]]

Java8流,一个表达式,没有其他库(两个解决方案,无需创建不必要的映射):

List<List<Integer>> partitionedList = IntStream.range(0, (list.size()-1)/targetSize+1)
.mapToObj(i -> list.subList(i*targetSize, Math.min(i*targetSize+targetSize, list.size())))
.collect(Collectors.toList());


List<List<Integer>> partitionedList2 = IntStream.iterate(0, i -> i < list.size(), i -> i + targetSize)
.mapToObj(i -> list.subList(i, Math.min(i + targetSize, list.size())))
.collect(Collectors.toList());

请记住,这些是子列表,因此对原始列表的更改也会影响这些子列表。

如果你不希望它们是子列表,而是新创建的独立列表,可以这样修改:

List<List<Integer>> partitionedList = IntStream.range(0, (list.size()-1)/targetSize+1)
.mapToObj(i -> IntStream.range(i*targetSize, Math.min(i*targetSize+targetSize, list.size())).mapToObj(j -> list.get(j)).collect(Collectors.toList()))
.collect(Collectors.toList());


List<List<Integer>> partitionedList2 = IntStream.iterate(0, i -> i < list.size(), i -> i + targetSize)
.mapToObj(i -> IntStream.range(i, Math.min(i + targetSize, list.size())).mapToObj(j -> list.get(j)).collect(Collectors.toList()))
.collect(Collectors.toList());
List<List<Integer>> allChunkLists = new ArrayList<List<Integer>>();
List<Integer> chunkList = null;
int fromIndex = 0;
int toIndex = CHUNK_SIZE;


while (fromIndex < origList.size()) {
chunkList = origList.subList(fromIndex, (toIndex > origList.size() ? origList.size() : toIndex));
allChunkLists.add(chunkList);
fromIndex = toIndex;
toIndex += CHUNK_SIZE;
}

没有库,只有Java的subList()toIndex需要被正确地限定,以避免subList()中的越界错误。