如何从Java中的数组中删除对象?
给定一个n对象的数组,假设它是一个string数组 ,它具有以下值:
foo[0] = "a"; foo[1] = "cc"; foo[2] = "a"; foo[3] = "dd";
我需要做些什么来删除/删除数组中的所有string/对象等于“a” ?
[如果您需要一些随时可用的代码,请滚动到我的“Edit3”(剪切后)。 其余的在这里为后代。]
充实Dustman的想法 :
List<String> list = new ArrayList<String>(Arrays.asList(array)); list.removeAll(Arrays.asList("a")); array = list.toArray(array);
编辑:我现在使用Arrays.asList
而不是Collections.singleton
:singleton被限制为一个条目,而asList
方法允许您添加其他string以稍后过滤: Arrays.asList("a", "b", "c")
。
编辑2:上面的方法保留相同的数组(所以数组仍然是相同的长度); 最后一个元素被设置为null。 如果你想要一个新的数组大小完全按照需要,使用这个,而不是:
array = list.toArray(new String[0]);
编辑3:如果您在同一个class级频繁使用此代码,则可以考虑将其添加到您的class级中:
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);
然后,这将停止乱扔你的堆用无用的空string数组,否则每当你的函数被调用时会被new
ed。
愤世嫉俗者的build议(见评论)也将有助于乱丢垃圾,为了公平,我应该提到它:
array = list.toArray(new String[list.size()]);
我更喜欢我的方法,因为它可能更容易得到明确的大小错误(例如,调用size()
在错误的列表)。
使用Arrays.asList()
从数组中取出List
,并在所有适当的元素上调用remove()
。 然后调用List上的toArray()
重新创build一个数组。
不是非常高效,但是如果你正确地封装它,你可以随时做更快的事情。
Java 8中的另一种select:
String[] filteredArray = Arrays.stream(array) .filter(e -> !e.equals(foo)).toArray(String[]::new);
你总是可以这样做:
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);
看下面的代码
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings)); a.remove(i); strings = new String[a.size()]; a.toArray(strings);
你可以使用外部库:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
它在项目Apache Commons Lang中http://commons.apache.org/lang/
如果您需要从数组中删除多个元素而不将其转换为List
或创build其他数组,则可以在O(n)中执行,而不依赖于要删除的项数。
这里, 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" }
小testing:
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()
。
关于做一个清单,然后删除,然后回到一个数组的事情罢工我错了。 没有经过testing,但我认为以下将performance更好。 是的,我可能过度优化。
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]; } }
我意识到这是一个非常古老的post,但这里的一些答案帮助我,所以这里是我的塔彭丝'ha'penny的价值!
我努力得到这个工作了很长一段时间之前,在我正在写回数组需要resize,除非对ArrayList
所做的更改保持列表大小不变。
如果您正在修改的ArrayList
的元素大于或小于它的元素,则List.toArray()
行将导致exception,所以您需要类似List.toArray(new String[] {})
或List.toArray(new String[0])
以创build具有新(正确)大小的数组。
听起来很明显,现在我知道了。 对于一个刚刚掌握新的,不熟悉的代码结构的Android / Java新手来说,这并不是那么明显,而且从前面的一些post来看也不是很明显,所以只是想让这个问题真正清楚,让别人像我一样小时候!
编辑:
数组中的空值点已被清除。 对不起,我的意见。
原版的:
呃…线
array = list.toArray(array);
将数组中所有删除的元素都用空值replace。 这可能是危险的 ,因为元素被删除,但数组的长度保持不变!
如果您想避免这种情况,请使用新的数组作为toArray()的参数。 如果你不想使用removeAll,Set将会是一个select:
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));
没有留下任何空值。
我对这个问题的贡献不大。
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; }
}
这里有很多答案 – 我看到的问题是,你没有说为什么你使用数组而不是集合,所以让我build议一些原因和哪些解决scheme适用(大多数解决scheme在这里其他的问题已经回答了,所以我不会详细说明):
原因:你不知道收集包是否存在或不信任
解决scheme:使用集合。
如果您打算从中间添加/删除,请使用LinkedList。 如果你真的担心大小或经常索引到集合的中间,使用ArrayList。 这两个都应该有删除操作。
理由:您关心的是大小,或者想要控制内存分配
解决scheme:使用具有特定初始大小的ArrayList。
ArrayList只是一个可以扩展的数组,但并不总是需要这样做。 这将是非常聪明的添加/删除项目,但再次如果您插入/从中间删除很多,使用LinkedList。
原因:你有一个数组进入和一个数组出去 – 所以你想操作一个数组
解决scheme:将其转换为ArrayList,删除项目并将其转换回来
原因:如果你自己做,你认为你可以写更好的代码
解决scheme:你不能,使用数组或链接列表。
理由:这是一个课堂作业,你不被允许,或者你由于某种原因没有权限访问apis
假设:你需要新的数组是正确的“大小”
解决scheme:扫描arrays以查找匹配项并对其进行计数。 创build一个正确大小的新数组(原始大小 – 匹配数)。 重复使用System.arraycopy将您希望保留的每个项目组复制到您的新arrays中。 如果这是一个类的分配,你不能使用System.arraycopy,只需一个一个地手工循环一个,但不要在生产代码中这样做,因为它慢得多。 (这些解决scheme在其他答案中都有详细说明)
理由:你需要运行裸机
假设:你不能不必要地分配空间或花太长时间
假设:您正在跟踪数组中使用的大小(长度),否则您将不得不重新分配您的数组以删除/插入。
一个为什么你可能想这样做的例子:一个单一的基元数组(比如说int值)正在占用你内存的很大一部分 – 比如50%! 一个ArrayList将强制这些成为指向Integer对象的指针列表,这将使用该内存量的几倍。
解决方法:迭代你的数组,每当你find一个要移除的元素(让我们称之为元素n),使用System.arraycopy将数组的尾部复制到“已删除”元素上(源和目标是相同的数组)足够聪明,以正确的方向进行复制,所以内存不会覆盖自身:
System.arraycopy(ary,n + 1,ary,n,length-n) 长度 - ;
如果您一次删除多个元素,您可能会希望比这更聪明。 你只会移动一个“匹配”和下一个之间的区域而不是整个尾部,并且一如既往,避免两次移动任何块。
在最后一种情况下,您绝对必须亲自完成这项工作,而使用System.arraycopy是真正实现这一目标的唯一方法,因为它将select最好的方法来移动计算机体系结构的内存 – 应该快很多倍比任何你可以合理编写自己的代码。
这取决于你的意思是“删除”? 一个数组是一个固定大小的构造 – 你不能改变其中的元素数量。 所以你可以a)创build一个新的,更短的,没有你不想要的元素的数组,或者b)把不需要的条目赋值给表示它们的“空”状态; 如果你不使用基元,通常为null。
在第一种情况下,从数组中创build一个列表,删除元素,并从列表中创build一个新的数组。 如果性能很重要,则将数组分配给不应删除的元素,然后从列表中创build一个新数组。 在第二种情况下,简单地通过并将空值分配给数组条目。
阿,我不能让代码正确显示。 对不起,我得到了它的工作。 对不起,我不认为我正确地读这个问题。
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++; } }
将复制索引为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) ); }
class sd { public static void main(String[ ] args) { System.out.println("Search and Delete"); int key; System.out.println("Enter the length of array:"); Scanner in=new Scanner(System.in); int n=in.nextInt(); int numbers[]=new int[n]; int i = 0; boolean found = false; System.out.println("Enter the elements in Array :"); for ( i = 0; i < numbers.length; i++) { numbers[i]=in.nextInt(); } System.out.println("The elements in Array are:"); for ( i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); } System.out.println("Enter the element to be searched:"); key=in.nextInt(); for ( i = 0; i < numbers.length; i++) { if (numbers[ i ] == key) { found = true; break; } } if (found) { System.out.println("Found " + key + " at index " + i + "."); numbers[i]=0;//haven't deleted the element in array System.out.println("After Deletion:"); for ( i = 0; i < numbers.length; i++) { if (numbers[ i ]!=0) { //it skips displaying element in array System.out.println(numbers[i]); } } } else { System.out.println(key + "is not in this array."); } } }//Sorry.. if there are mistakes.
使用:
list.removeAll(...); //post what char you need in the ... section
将空值分配给arrays位置。