从数组中删除第一个元素的最佳方法是什么?

102

我有一个字符串数组 (String[]),需要移除第一个元素。如何高效地做到这一点?


1
可能是如何在Java中从数组中删除对象?的重复问题。 - McDowell
5
不是重复问题。之前的问题是关于按值删除项目,而这个问题是关于按索引删除项目。 - james.garriss
6个回答

186

在Java中,数组的大小是不可变的。因此,在技术上,您无法从数组中删除任何元素。

模拟从数组中删除元素的一种方法是创建一个新的、更小的数组,然后将原始数组中的所有元素复制到新的、更小的数组中。

String[] yourArray = Arrays.copyOfRange(oldArr, 1, oldArr.length);

然而,我不建议使用上述方法。你应该真正使用一个List<String>。列表允许你在任何索引处添加和删除项目。代码如下:

List<String> list = new ArrayList<String>(); // or LinkedList<String>();
list.add("Stuff");
// add lots of stuff
list.remove(0); // removes the first item

38
需要注意的是,删除ArrayList的第一个元素的时间复杂度为O(n)。 - Matthew Flaschen
1
@Matt,涉及到数组和列表。不过,针对列表的代码要简单得多。 - jjnguy
18
适用于数组和ArrayList,但不适用于LinkedList。 - Matthew Flaschen
5
O(n)?嗯...在C数组中吗?要删除第一个元素,你只需要增加指针 O(1)。 - Hernán Eche
3
对于像我一样在Android中使用Java的人,Arrays.copyOfRange()是适用于API9及以上版本的。 - Sdghasemi
显示剩余5条评论

16

可能最简单的方法是如下所示——你需要构建一个新数组,该新数组比原数组少一个元素,然后将要保留的元素复制到正确的位置。

int n=oldArray.length-1;
String[] newArray=new String[n];
System.arraycopy(oldArray,1,newArray,0,n);

请注意,如果您经常执行这类操作,那么这可能表明您实际上应该使用不同类型的数据结构,例如链表。每次构造新数组都是O(n)操作,如果您的数组很大,则会变得昂贵。链表将为您提供O(1)删除第一个元素的能力。

另一种想法是根本不删除第一个项,而只是增加指向第一个正在使用的索引的整数值。数组的用户需要考虑此偏移量,但这可能是一种有效的方法。Java String类实际上在创建子字符串时内部使用此方法。


4
这并不是从技术角度来说最简单的方式,Arrays.copyOfRange() 才是。 - jjnguy
5
他正在使用Java6,因此可以使用更紧凑的Arrays.copyOfRange函数。 - Thilo
1
@Justin - 当然可以,但只有在你的目标是Java 1.6或更高版本时。 - mikera
1
返回翻译后的文本:true。它并不总是适用。 - jjnguy
6
问题的标题明确表示提问者对Java 1.6及以上版本的答案感兴趣。 - Stephen C

5
你根本无法做到,更不用说快速了。在Java中,数组的大小是固定的。你可以做两件事:
  1. 将每个元素向上移动一个位置,然后将最后一个元素设置为null。
  2. 创建一个新数组,然后复制它。
你可以使用System.arraycopy来执行这两个操作。由于它们都会复制除1个元素外的所有元素,因此这两个操作的时间复杂度均为O(n)。
如果你经常需要删除第一个元素,请考虑使用LinkedList。你可以使用LinkedList.remove来方便地删除第一个元素,该方法来自于Queue接口。使用LinkedList,删除第一个元素的时间复杂度为O(1)。事实上,一旦你有了指向该位置的ListIterator,删除任何元素的时间复杂度都是O(1)。但是,通过索引访问任意元素的时间复杂度为O(n)。

3

保留数组的第一个“活动”元素的索引。删除(假装删除)第一个元素然后变成了O(1)时间复杂度的操作。


-1
总之,快速链表方法:
List<String> llist = new LinkedList<String>(Arrays.asList(oldArray));
llist.remove(0);

问题是关于Java数组,而不是列表。 - Malinda

-13
一个替代的丑陋方法:
   String[] a ={"BLAH00001","DIK-11","DIK-2","MAN5"};
   String[] k=Arrays.toString(a).split(", ",2)[1].split("]")[0].split(", ");

2
请有足够声望的人给这个答案点个踩——它就是它所说的那样——丑陋!没有恶意,但为了代码可读性,请不要发布这种东西! - Hack5
如果您已经在使用数组,最好使用Arrays.copyOfRange。 - Bishal Gautam
他询问了最佳的方式。 - Sapphire_Brick
不要删除它,否则您将失去声望。 - Sapphire_Brick
不要展示丑陋的东西,你已经知道了。 - endyey Es
1
如果数组中的字符串包含 ", ",则此方法无法正常工作。 - jjnguy

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