提问人:ramayac 提问时间:9/22/2008 最后编辑:Peter Mortensenramayac 更新时间:2/24/2021 访问量:384991
如何在 Java 中从数组中删除对象?
How do I remove objects from an array in Java?
问:
给定一个包含 n 个对象的数组,假设它是一个字符串数组,它具有以下值:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
我必须做什么才能删除/移除数组中所有等于“a”的字符串/对象?
答:
用 做一个数组,并调用所有适当的元素。然后调用“列表”以再次重新制作成数组。List
Arrays.asList()
remove()
toArray()
性能不是很好,但如果你正确地封装它,你以后总是可以更快地做一些事情。
评论
Arrays.asList()
remove()
将 null 分配给数组位置。
[如果你想要一些现成的代码,请滚动到我的“Edit3”(剪切后)。其余的都在这里供后代使用。
为了充实 Dustman 的想法:
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
编辑:我现在使用代替:singleton仅限于一个条目,而该方法允许您添加其他字符串以稍后过滤掉:。Arrays.asList
Collections.singleton
asList
Arrays.asList("a", "b", "c")
Edit2:上述方法保留了相同的数组(因此数组的长度仍然相同);最后一个后面的元素设置为 null。如果想要一个大小完全符合要求的新数组,请改用以下方法:
array = list.toArray(new String[0]);
编辑 3:如果您在同一类中频繁使用此代码,您可能希望考虑将其添加到您的类中:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
然后,函数变为:
List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.removeAll(Arrays.asList("a"));
array = list.toArray(EMPTY_STRING_ARRAY);
这样一来,就不会再在堆堆里乱扔无用的空字符串数组,否则每次调用函数时都会被 ed。new
愤世嫉俗者的建议(见评论)也将有助于解决乱扔垃圾的问题,为了公平起见,我应该提到它:
array = list.toArray(new String[list.size()]);
我更喜欢我的方法,因为可能更容易弄错显式大小(例如,调用错误的列表)。size()
评论
关于列出它然后删除然后回到数组的某些东西让我感到错误。尚未测试,但我认为以下内容会表现得更好。是的,我可能过度预优化了。
boolean [] deleteItem = new boolean[arr.length];
int size=0;
for(int i=0;i<arr.length;i==){
if(arr[i].equals("a")){
deleteItem[i]=true;
}
else{
deleteItem[i]=false;
size++;
}
}
String[] newArr=new String[size];
int index=0;
for(int i=0;i<arr.length;i++){
if(!deleteItem[i]){
newArr[index++]=arr[i];
}
}
哎呀,我无法让代码正确显示。对不起,我让它工作了。再次抱歉,我认为我没有正确阅读这个问题。
String foo[] = {"a","cc","a","dd"},
remove = "a";
boolean gaps[] = new boolean[foo.length];
int newlength = 0;
for (int c = 0; c<foo.length; c++)
{
if (foo[c].equals(remove))
{
gaps[c] = true;
newlength++;
}
else
gaps[c] = false;
System.out.println(foo[c]);
}
String newString[] = new String[newlength];
System.out.println("");
for (int c1=0, c2=0; c1<foo.length; c1++)
{
if (!gaps[c1])
{
newString[c2] = foo[c1];
System.out.println(newString[c2]);
c2++;
}
}
编辑:
数组中具有空值的点已被清除。对不起我的评论。
源语言:
嗯......线
array = list.toArray(array);
将数组中已删除元素所在的所有间隙替换为 null。这可能很危险,因为元素被删除了,但数组的长度保持不变!
如果要避免这种情况,请使用新的 Array 作为 toArray() 的参数。如果您不想使用 removeAll,则 Set 将是一个替代方法:
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
Set<String> asSet = new HashSet<String>(Arrays.asList(array));
asSet.remove("a");
array = asSet.toArray(new String[] {});
System.out.println(Arrays.toString(array));
给:
[a, bc, dc, a, ef]
[dc, ef, bc]
正如克里斯·耶斯特·杨(Chris Yester Young)目前接受的答案所输出的那样:
[a, bc, dc, a, ef]
[bc, dc, ef, null, ef]
使用代码
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
System.out.println(Arrays.toString(array));
不留下任何 null 值。
评论
你总是可以做到的:
int i, j;
for (i = j = 0; j < foo.length; ++j)
if (!"a".equals(foo[j])) foo[i++] = foo[j];
foo = Arrays.copyOf(foo, i);
这取决于你说的“删除”是什么意思?数组是一个固定大小的构造 - 你不能改变其中的元素数量。因此,您可以 a) 创建一个新的、更短的数组,而没有您不想要的元素,或者 b) 将您不想要的条目分配给指示其“空”状态的东西;如果不使用基元,则通常为 null。
在第一种情况下,从数组创建一个 List,删除元素,然后从列表中创建一个新数组。如果性能很重要,请循环访问数组,将不应删除的任何元素分配到列表中,然后从列表中创建一个新数组。在第二种情况下,只需遍历并将 null 分配给数组条目。
您可以使用外部库:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
它位于 Apache Commons Lang http://commons.apache.org/lang/ 项目中
评论
ArrayUtils.removeElement(boolean[] array, boolean element)
也非常有用。
我意识到这是一个非常古老的帖子,但这里的一些答案帮助了我,所以这是我的 tuppence' ha'penny's worth!
在纠结我写回的数组需要调整大小之前,我努力让它工作了很长一段时间,除非对列表大小保持不变所做的更改。ArrayList
如果您正在修改的元素最终比开始时多或少,则该行将导致异常,因此您需要类似 or 的东西才能创建具有新(正确)大小的数组。ArrayList
List.toArray()
List.toArray(new String[] {})
List.toArray(new String[0])
现在我知道了,这听起来很明显。对于一个正在掌握新的和不熟悉的代码结构的 Android/Java 新手来说,这并不那么明显,而且从这里的一些早期帖子中也不明显,所以只是想让其他任何人真正清楚地了解这一点像我一样挠头几个小时!
评论
我对这个问题的贡献很小。
public class DeleteElementFromArray {
public static String foo[] = {"a","cc","a","dd"};
public static String search = "a";
public static void main(String[] args) {
long stop = 0;
long time = 0;
long start = 0;
System.out.println("Searched value in Array is: "+search);
System.out.println("foo length before is: "+foo.length);
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
System.out.println("==============================================================");
start = System.nanoTime();
foo = removeElementfromArray(search, foo);
stop = System.nanoTime();
time = stop - start;
System.out.println("Equal search took in nano seconds = "+time);
System.out.println("==========================================================");
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
}
public static String[] removeElementfromArray( String toSearchfor, String arr[] ){
int i = 0;
int t = 0;
String tmp1[] = new String[arr.length];
for(;i<arr.length;i++){
if(arr[i] == toSearchfor){
i++;
}
tmp1[t] = arr[i];
t++;
}
String tmp2[] = new String[arr.length-t];
System.arraycopy(tmp1, 0, tmp2, 0, tmp2.length);
arr = tmp2; tmp1 = null; tmp2 = null;
return arr;
}
}
评论
请参阅下面的代码
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);
Java 8 中的另一种选择:
String[] filteredArray = Arrays.stream(array)
.filter(e -> !e.equals(foo)).toArray(String[]::new);
评论
Stream.of(foo).filter(s -> ! s.equals("a")).toArray()
如果您需要从数组中删除多个元素而不将其转换为其他数组,则可以在 O(n) 中执行此操作,而不依赖于要删除的项目数。List
这里,是初始数组,是要删除的元素的不同有序索引(位置):a
int... r
public int removeItems(Object[] a, int... r) {
int shift = 0;
for (int i = 0; i < a.length; i++) {
if (shift < r.length && i == r[shift]) // i-th item needs to be removed
shift++; // increment `shift`
else
a[i - shift] = a[i]; // move i-th item `shift` positions left
}
for (int i = a.length - shift; i < a.length; i++)
a[i] = null; // replace remaining items by nulls
return a.length - shift; // return new "length"
}
小测试:
String[] a = {"0", "1", "2", "3", "4"};
removeItems(a, 0, 3, 4); // remove 0-th, 3-rd and 4-th items
System.out.println(Arrays.asList(a)); // [1, 2, null, null, null]
在您的任务中,您可以先扫描数组以收集“a”的位置,然后调用 。removeItems()
评论
将复制除索引为 i 的元素之外的所有元素:
if(i == 0){
System.arraycopy(edges, 1, copyEdge, 0, edges.length -1 );
}else{
System.arraycopy(edges, 0, copyEdge, 0, i );
System.arraycopy(edges, i+1, copyEdge, i, edges.length - (i+1) );
}
这里有很多答案——我所看到的问题是你没有说为什么你使用数组而不是集合,所以让我提出几个原因以及哪些解决方案适用(大多数解决方案已经在这里的其他问题中得到了解答,所以我不会太详细):
原因:您不知道收集包的存在或不信任它
解决方案:使用集合。
如果您计划从中间添加/删除,请使用 LinkedList。如果您真的担心大小或经常索引到集合的中间,请使用 ArrayList。这两者都应该有删除操作。
原因:您担心大小或想要控制内存分配
解决方案:使用具有特定初始大小的 ArrayList。
ArrayList 只是一个可以扩展自身的数组,但它并不总是需要这样做。添加/删除项目将非常聪明,但同样,如果您要从中间插入/删除 LOT,请使用 LinkedList。
reason:你有一个数组进入,一个数组输出 -- 所以你想对一个数组进行操作
解决方案:将其转换为 ArrayList,删除该项并将其转换回来
reason:你认为自己做可以写出更好的代码
解决方案:你不能,使用数组或链表。
原因:这是一项类作业,不允许您访问,或者由于某种原因您无权访问集合 API
assumption:您需要新数组的“大小”正确
溶液: 扫描数组以查找匹配的项目并对其进行计数。创建一个正确大小的新数组(原始大小 - 匹配数)。重复使用 System.arraycopy 将要保留的每组项复制到新 Array 中。如果这是一个类赋值,并且您不能使用 System.arraycopy,只需在循环中一次手动复制一个,但永远不要在生产代码中执行此操作,因为它要慢得多。(这些解决方案在其他答案中都有详细说明)
原因:您需要运行裸机
假设:您不得不必要地分配空间或花费太长时间
假设:您正在单独跟踪数组中使用的大小(长度),否则您必须重新分配数组以进行删除/插入。
举个例子来说明你为什么可能想要这样做:一个基元数组(比如说 int 值)占用了你的 ram 的很大一部分——比如 50%!ArrayList 会强制这些对象进入指向 Integer 对象的指针列表,这些对象将使用几倍于该内存量的内存。
解决方案:遍历你的数组,每当你找到一个要删除的元素(我们称之为元素 n)时,使用 System.arraycopy 将数组的尾部复制到“已删除”元素上(源和目标是同一个数组)——它足够聪明,可以在正确的方向上进行复制,这样内存就不会覆盖自己:
System.arraycopy(ary, n+1, ary, n, length-n) length--;
如果您一次删除多个元素,您可能希望比这更聪明。您只会移动一个“匹配”和下一个“匹配”之间的区域,而不是整个尾巴,并且一如既往地避免两次移动任何块。
在最后一种情况下,你绝对必须自己做这项工作,而使用 System.arraycopy 确实是唯一的方法,因为它将选择最好的方式来移动你的计算机体系结构的内存——它应该比你自己合理编写的任何代码快很多倍。
初始数组
int[] array = {5,6,51,4,3,2};
如果要删除索引 2 的 51,请使用以下命令
for(int i = 2; i < array.length -1; i++){
array[i] = array[i + 1];
}
在字符串数组中,例如
String name = 'a b c d e a f b d e' // 可以像 String name = 'aa bb c d e aa f bb d e'
我构建了以下类
class clearname{
def parts
def tv
public def str = ''
String name
clearname(String name){
this.name = name
this.parts = this.name.split(" ")
this.tv = this.parts.size()
}
public String cleared(){
int i
int k
int j=0
for(i=0;i<tv;i++){
for(k=0;k<tv;k++){
if(this.parts[k] == this.parts[i] && k!=i){
this.parts[k] = '';
j++
}
}
}
def str = ''
for(i=0;i<tv;i++){
if(this.parts[i]!='')
this.str += this.parts[i].trim()+' '
}
return this.str
}}
return new clearname(name).cleared()
得到这个结果
a、b、c、d、e、f
希望此代码对任何人有所帮助 问候
如果元素的顺序无关紧要。您可以在元素 foo[x] 和 foo[0] 之间交换,然后调用 foo.drop(1)。
foo.drop(n)
从数组中删除 (n) 个第一个元素。
我想这是最简单和资源高效的方法。
PS:可以通过多种方式实现,这是我的版本。indexOf
Integer indexOf(String[] arr, String value){
for(Integer i = 0 ; i < arr.length; i++ )
if(arr[i] == value)
return i; // return the index of the element
return -1 // otherwise -1
}
while (true) {
Integer i;
i = indexOf(foo,"a")
if (i == -1) break;
foo[i] = foo[0]; // preserve foo[0]
foo.drop(1);
}
使用 lambda 仅删除几个相等条目
中的第一个
boolean[] done = {false};
String[] arr = Arrays.stream( foo ).filter( e ->
! (! done[0] && Objects.equals( e, item ) && (done[0] = true) ))
.toArray(String[]::new);
可以删除条目null
评论