在Java中将List拆分为两个子列表的最简单,最标准和/或最有效的方法是什么?改变原始列表是可以的,因此不需要复制。方法签名可以是
/** Split a list into two sublists. The original list will be modified to
* have size i and will contain exactly the same elements at indices 0
* through i-1 as it had originally; the returned list will have size
* len-i (where len is the size of the original list before the call)
* and will have the same elements at indices 0 through len-(i+1) as
* the original list had at indices i through len-1.
*/
<T> List<T> split(List<T> list, int i);
[EDIT] List.subList
返回原始列表中的视图,如果修改了原始列表,该视图将无效。因此,split
不能使用subList
,除非它还省略了原始引用(或者,如在Marc Novakowski的回答中,使用subList
但是立即复制结果)。
答案 0 :(得分:54)
快速半伪代码:
List sub=one.subList(...);
List two=new XxxList(sub);
sub.clear(); // since sub is backed by one, this removes all sub-list items from one
它使用标准的List实现方法,并避免所有在循环中运行。对于大多数列表,clear()方法也将使用内部removeRange()
并且效率更高。
答案 1 :(得分:30)
您可以使用常用实用程序,例如Guava库:
import com.google.common.collect.Lists;
import com.google.common.math.IntMath;
import java.math.RoundingMode;
int partitionSize = IntMath.divide(list.size(), 2, RoundingMode.UP);
List<List<T>> partitions = Lists.partition(list, partitionSize);
结果是两个列表的列表 - 不完全符合您的规范,但如果需要,您可以轻松进行调整。
答案 2 :(得分:5)
重复Marc's solution,此解决方案使用for
循环来保存对list.size()
的一些调用:
<T> List<T> split(List<T> list, int i) {
List<T> x = new ArrayList<T>(list.subList(i, list.size()));
// Remove items from end of original list
for (int j=list.size()-1; j>i; --j)
list.remove(j);
return x;
}
答案 3 :(得分:4)
使用subList方法获取返回的数组非常简单,但我知道从List中删除一系列项目并不容易。
这就是我所拥有的:
<T> List<T> split(List<T> list, int i) {
List<T> x = new ArrayList<T>(list.subList(i, list.size()));
// Remove items from end of original list
while (list.size() > i) {
list.remove(list.size() - 1);
}
return x;
}
答案 4 :(得分:4)
我需要类似的东西,所以这是我的实施。它允许调用者指定应返回List的哪个实现:
package com.mrojas.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListUtils {
/**
* Splits a list into smaller sublists.
* The original list remains unmodified and changes on the sublists are not propagated to the original list.
*
*
* @param original
* The list to split
* @param maxListSize
* The max amount of element a sublist can hold.
* @param listImplementation
* The implementation of List to be used to create the returned sublists
* @return A list of sublists
* @throws IllegalArgumentException
* if the argument maxListSize is zero or a negative number
* @throws NullPointerException
* if arguments original or listImplementation are null
*/
public static final <T> List<List<T>> split(final List<T> original, final int maxListSize,
final Class<? extends List> listImplementation) {
if (maxListSize <= 0) {
throw new IllegalArgumentException("maxListSize must be greater than zero");
}
final T[] elements = (T[]) original.toArray();
final int maxChunks = (int) Math.ceil(elements.length / (double) maxListSize);
final List<List<T>> lists = new ArrayList<List<T>>(maxChunks);
for (int i = 0; i < maxChunks; i++) {
final int from = i * maxListSize;
final int to = Math.min(from + maxListSize, elements.length);
final T[] range = Arrays.copyOfRange(elements, from, to);
lists.add(createSublist(range, listImplementation));
}
return lists;
}
/**
* Splits a list into smaller sublists. The sublists are of type ArrayList.
* The original list remains unmodified and changes on the sublists are not propagated to the original list.
*
*
* @param original
* The list to split
* @param maxListSize
* The max amount of element a sublist can hold.
* @return A list of sublists
*/
public static final <T> List<List<T>> split(final List<T> original, final int maxListSize) {
return split(original, maxListSize, ArrayList.class);
}
private static <T> List<T> createSublist(final T[] elements, final Class<? extends List> listImplementation) {
List<T> sublist;
final List<T> asList = Arrays.asList(elements);
try {
sublist = listImplementation.newInstance();
sublist.addAll(asList);
} catch (final InstantiationException e) {
sublist = asList;
} catch (final IllegalAccessException e) {
sublist = asList;
}
return sublist;
}
}
以及一些测试用例:
package com.mrojas.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
public class ListUtilsTest {
@Test
public void evenSplitTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 2, LinkedList.class);
assertEquals(5, sublists.size());
for (final List<Object> sublist : sublists) {
assertEquals(2, sublist.size());
assertTrue(sublist instanceof LinkedList<?>);
}
}
@Test
public void unevenSplitTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 3, LinkedList.class);
assertEquals(4, sublists.size());
assertEquals(3, sublists.get(0).size());
assertEquals(3, sublists.get(1).size());
assertEquals(3, sublists.get(2).size());
assertEquals(1, sublists.get(3).size());
}
@Test
public void greaterThanSizeSplitTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 20, LinkedList.class);
assertEquals(1, sublists.size());
assertEquals(10, sublists.get(0).size());
}
@Test
public void emptyListSplitTest() {
final List<List<Object>> sublists = ListUtils.split(Collections.emptyList(), 10, LinkedList.class);
assertEquals(0, sublists.size());
}
@Test(expected=IllegalArgumentException.class)
public void negativeChunkSizeTest() {
ListUtils.split(getPopulatedList(5), -10, LinkedList.class);
}
@Test
public void invalidClassTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 2, LinkedList.class);
assertEquals(5, sublists.size());
for (final List<Object> sublist : sublists) {
assertEquals(2, sublist.size());
assertTrue(sublist instanceof LinkedList<?>);
}
}
private List<Object> getPopulatedList(final int size) {
final List<Object> list = new ArrayList<Object>(10);
for (int i = 0; i < 10; i++) {
list.add(new Object());
}
return list;
}
}
答案 5 :(得分:3)
import java.util.Collection;
public class CollectionUtils {
/**
* Will split the passed collection so that the size of the new collections
* is not greater than maxSize
* @param t
* @param maxSize
* @return a List containing splitted collections
*/
@SuppressWarnings("unchecked")
public static <T> List<Collection<T>>split(Collection<T> t, int maxSize) {
int counter = 0;
List<Collection<T>> ret = new LinkedList<Collection<T>>();
Iterator<T>itr = t.iterator();
try {
Collection<T> tmp = t.getClass().newInstance();
ret.add(tmp);
while(itr.hasNext()) {
tmp.add(itr.next());
counter++;
if(counter>=maxSize && itr.hasNext()) {
tmp = t.getClass().newInstance();
ret.add(tmp);
counter=0;
}
}
} catch(Throwable e) {
Logger.getLogger(CollectionUtils.class).error("There was an error spliting "+t.getClass(),e);
}
return ret;
}
}
// JUnit test cases
import java.util.ArrayList;
/**
*
* $Change$
* @version $Revision$
* Last modified date & time $DateTime$
*/
public class CollectionUtilsTest {
@Test
public void testSplitList() {
List<Integer>test = new ArrayList<Integer>(100);
for (int i=1;i<101;i++) {
test.add(i);
}
List<Collection<Integer>> tests = CollectionUtils.split(test, 10);
Assert.assertEquals("Size mismatch", 10,tests.size());
TreeSet<Integer> tmp = new TreeSet<Integer>();
for(Collection<Integer> cs:tests) {
for(Integer i:cs) {
Assert.assertFalse("Duplicated item found "+i,tmp.contains(i));
tmp.add(i);
}
System.out.println(cs);
}
int why = 1;
for(Integer i:tmp) {
Assert.assertEquals("Not all items are in the collection ",why,i.intValue());
why++;
}
}
@Test
public void testSplitSet() {
TreeSet<Integer>test = new TreeSet<Integer>();
for (int i=1;i<112;i++) {
test.add(i);
}
List<Collection<Integer>> tests = CollectionUtils.split(test, 10);
Assert.assertEquals("Size mismatch", 12,tests.size());
TreeSet<Integer> tmp = new TreeSet<Integer>();
int cI = 0;
for(Collection<Integer> cs:tests) {
for(Integer i:cs) {
Assert.assertFalse("Duplicated item found "+i,tmp.contains(i));
tmp.add(i);
}
// if(cI>10) {
System.out.println(cs);
// }
cI++;
}
int why = 1;
for(Integer i:tmp) {
Assert.assertEquals("Not all items are in the collection ",why,i.intValue());
why++;
}
}
}
答案 6 :(得分:3)
我使用“Apache Commons Collections 4”库。它在ListUtils类中有一个分区方法:
...
int targetSize = 100;
List<Integer> largeList = ...
List<List<Integer>> output = ListUtils.partition(largeList, targetSize);
答案 7 :(得分:1)
<T> List<T> split(List<T> list, int i) {
List<T> secondPart = list.sublist(i, list.size());
List<T> returnValue = new ArrayList<T>(secondPart());
secondPart.clear(),
return returnValue;
}
答案 8 :(得分:1)
将列表拆分为特定大小列表的通用函数。我在java集合中长期缺少这一点。
private List<List<T>> splitList(List<T> list, int maxListSize) {
List<List<T>> splittedList = new ArrayList<List<T>>();
int itemsRemaining = list.size();
int start = 0;
while (itemsRemaining != 0) {
int end = itemsRemaining >= maxListSize ? (start + maxListSize) : itemsRemaining;
splittedList.add(list.subList(start, end));
int sizeOfFinalList = end - start;
itemsRemaining = itemsRemaining - sizeOfFinalList;
start = start + sizeOfFinalList;
}
return splittedList;
}
答案 9 :(得分:0)
同样地从Marc的列表中删除,我们将使用List.removeAll()从第二个列表中删除重复的条目。请注意,严格来说,如果原始列表中没有重复项目,则仅遵循规范:否则,原始列表可能缺少项目。
<T> List<T> split(List<T> list, int i) {
List<T> x = new ArrayList<T>(list.subList(i, list.size()));
// Remove items from end of original list
list.removeAll(x);
return x;
}
答案 10 :(得分:0)
示例java代码拆分列表
公开名单&gt; split(列表列表,int i){
List<List<Long>> out = new ArrayList<List<Long>>();
int size = list.size();
int number = size/i;
int remain = size % i;
if(remain != 0){
number++;
}
for(int j=0; j < number; j++){
int start = j * i;
int end = start+ i;
if(end > list.size()){
end = list.size();
}
out.add(list.subList(start, end));
}
return out;
}
答案 11 :(得分:0)
我的解决方案:
List<X> listToSplit = new ArrayList<X>();
List<X> list1 = new ArrayList<X>();
List<X> list2 = new ArrayList<X>();
for (X entry : listToSplit)
{
if (list1.size () > list2.size ())
list2.add (entry);
else
list1.add( entry );
}
应该工作:)
答案 12 :(得分:0)
//Here is my list
ArrayList<T> items=new ArrayList<T>();
Integer startIndex = 0;
int j = 0;
for (; j < items.size() - 1; j++) {//always start with next index not again 0
for (int i = 0; i < 4; i++) { // divide into equal part with 4 item
startIndex = startIndex + 1;
j = startIndex;
}
}
答案 13 :(得分:0)
使用流的解决方案,对每个项目使用切换/翻转布尔值进行分区:
print(df.iloc[2,2:,2:4].min(axis=1))
您最终得到一个包含两个条目的映射,键是Collection<String> big = ...;
AtomicBoolean switcheroo = new AtomicBoolean();
Map<Boolean, List<String>> subLists = big.stream()
.collect(Collectors.partitioningBy(o -> switcheroo.getAndSet(!switcheroo.get())));
和true
,值是子列表。
这并不能完全回答原始问题,但是您可以使用每次递增的false
而不是AtomicInteger
。