复制ArrayList的前一半元素

3

有一个 ArrayList<Integer> al,我想将它的前一半元素复制到另一个 ArrayList<Integer> firstHalf 中。(如果 al 的元素个数为奇数,则 firstHalf 应该多一个元素。)但是,下面的代码会抛出一个 IndexOutOfBoundsException,并显示 Index: 0, Size: 0,尽管我不确定这会是什么问题,因为 ArrayList 的索引从 0 开始。此外,我知道可以使用 .arraycopy,但我想用 for 循环来实现。

 int x = al.size()/2 + (al.size()%2) - 1;
 for(int i = 0; i < x; i++){
    firstHalf.set(i, al.get(i));
 }

2
考虑使用 subList - Sotirios Delimanolis
1
@SotiriosDelimanolis 注意事项:subList() 返回的是原始列表的“视图”,而不是副本。因此,您需要像这样使用firstHalf = new ArrayList(al.subList(0, newSize));来创建新的列表。 - millimoose
4个回答

10

List#subList非常适合这个目的。

int chunkSize = al.size() % 2 == 0 ? al.size() / 2 : (al.size() / 2) + 1;
List<Integer> firstHalf = al.subList(0, chunkSize);

需要考虑两种情况:

  • 偶数:如果大小为偶数,则n / 2是正确的分块大小。
  • 奇数:如果大小为奇数,则需要将结果加1,以使奇数长度的列表具有中间值。

你确定最后一句话是这样的吗?在给出“from”和“to”索引时,惯例是“to”索引是排除在外的。(更重要的是,Javadoc说它是排除在外的。) - millimoose
好的,发现了。我不太确定当时我在想什么。在该值的末尾加1应该可以纠正这个问题。 - Makoto
现在你已经破坏了元素数量为偶数的列表。提示:如果你必须使用模算术而不是添加一个“if”语句,那么公式为((al.size() + 1) / 2) - 1 - millimoose
又抓住我了。希望这次修好了。 - Makoto
如果我想要一个ArrayList<Integer>怎么办?我尝试过强制转换,但它显示“java.util.RandomAcessSubList无法转换为java.util.ArrayList”(抱歉,我在这个领域是个新手!)。 - javaChipFrapp
2
@howAnAngel_Dies_ 请看我在问题下面的评论。只需使用 new ArrayList(al.sublist(…)); 来复制即可。 - millimoose

7
你应该使用add而不是set:
int x = al.size()/2 + (al.size()%2) - 1;
for(int i = 0; i < x; i++){
    firstHalf.add(al.get(i));
 }

最好使用List#subList

来实现。


啊,谢谢,我忘了那个。不过我在想,为什么 .set 不起作用呢? - javaChipFrapp
2
@howAnAngel_Dies_ 要使用 set,你的列表不能是空的。如果你执行 firstHalf.set(0, something),而你的列表是空的,那么索引为 0 的元素不存在,因此它无法被设置。 - BackSlash
1
由阅读Javadoc委员会为您推荐:@howAnAngel_Dies_ "替换此列表中指定位置的元素为指定的元素。" - millimoose

2

另一种方法:

List<Integer> firstHalf = al.subList(0, al.size()/2 + (al.size()%2) - 1);

0
List<Integer> firstHalf = al.subList(0, (int) al.size() / 2 + 1);

将al.size() / 2转换为整数比使用"%2"更容易。

你可以将firstHalf加1,使其大于后半部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接