给定一个包含n 个对象的数组,假设它是一个字符串数组,它具有以下值:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
我该怎么做才能删除/删除数组中等于“a”的所有字符串/对象?
给定一个包含n 个对象的数组,假设它是一个字符串数组,它具有以下值:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
我该怎么做才能删除/删除数组中等于“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
: 单例仅限于一个条目,而该asList
方法允许您添加其他字符串以稍后过滤掉:Arrays.asList("a", "b", "c")
.
Edit2:上述方法保留相同的数组(因此数组仍然是相同的长度);最后一个元素设置为null。如果您想要一个大小完全符合要求的新数组,请改用:
array = list.toArray(new String[0]);
Edit3:如果您在同一个课程中经常使用此代码,您可能希望考虑将其添加到您的课程中:
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);
然后,这将停止在您的堆中乱扔无用的空字符串数组,否则new
每次调用您的函数时都会被编辑。
愤世嫉俗的人的建议(见评论)也将有助于乱扔垃圾,为了公平起见,我应该提一下:
array = list.toArray(new String[list.size()]);
我更喜欢我的方法,因为它可能更容易弄错明确的大小(例如,调用size()
错误的列表)。
Java 8 中的替代方案:
String[] filteredArray = Arrays.stream(array)
.filter(e -> !e.equals(foo)).toArray(String[]::new);
使用List
,从数组中创建一个Arrays.asList()
,并调用remove()
所有适当的元素。然后调用toArray()
“列表”再次返回数组。
性能不是很好,但如果你正确封装它,你以后总是可以更快地做一些事情。
你总是可以这样做:
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);
您可以使用外部库:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
它在项目 Apache Commons Lang http://commons.apache.org/lang/
请参阅下面的代码
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);
如果您需要从数组中删除多个元素而不将其转换为List
或创建其他数组,则可以在 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"
}
小测试:
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()
.
这里有很多答案 - 我看到的问题是你没有说为什么你使用数组而不是集合,所以让我提出几个原因以及哪些解决方案将适用(大多数解决方案这里的其他问题已经回答了,所以我不会太详细):
原因:您不知道收藏包存在或不信任它
解决方案:使用集合。
如果您打算从中间添加/删除,请使用 LinkedList。如果您真的担心大小或经常索引到集合的中间,请使用 ArrayList。这两个都应该有删除操作。
原因:您关心大小或希望控制内存分配
解决方案:使用具有特定初始大小的 ArrayList。
ArrayList 只是一个可以扩展自身的数组,但它并不总是需要这样做。添加/删除项目将非常聪明,但是如果您要从中间插入/删除很多,请再次使用 LinkedList。
原因:你有一个数组进来和一个数组出去——所以你想对一个数组进行操作
解决方案:将其转换为ArrayList,删除该项目并将其转换回
原因:你认为如果你自己做,你可以写出更好的代码
解决方案:你不能,使用数组或链表。
原因:这是一项课堂作业,您不被允许或由于某种原因您无权访问集合 API
假设:您需要新数组是正确的“大小”
解决方案:扫描数组以查找匹配项并计数。创建一个正确大小的新数组(原始大小 - 匹配数)。重复使用 System.arraycopy 将您希望保留的每组项目复制到新数组中。如果这是一个类分配并且您不能使用 System.arraycopy,只需在循环中手动一次复制一个,但不要在生产代码中这样做,因为它要慢得多。(这些解决方案在其他答案中都有详细说明)
原因:你需要运行裸机
假设:您不得不必要地分配空间或花费太长时间
假设:您正在单独跟踪数组中使用的大小(长度),否则您必须为删除/插入重新分配数组。
您可能想要这样做的一个示例:单个基元数组(假设是 int 值)占用了您的 ram 的很大一部分——比如 50%!ArrayList 会强制将它们放入指向 Integer 对象的指针列表,这些对象将使用该内存量的几倍。
解决方案:遍历您的数组,每当您找到要删除的元素(我们称其为元素 n),使用 System.arraycopy 将数组的尾部复制到“已删除”元素上(源和目标是相同的数组) - 它足够聪明,可以按照正确的方向进行复制,因此内存不会覆盖自身:
System.arraycopy(ary, n+1, ary, n, 长度-n) 长度 - ;
如果您一次删除多个元素,您可能希望比这更聪明。您只会移动一个“匹配”和下一个“匹配”之间的区域,而不是整个尾部,并且一如既往,避免移动任何块两次。
在最后一种情况下,您绝对必须自己完成工作,并且使用 System.arraycopy 确实是唯一的方法,因为它将为您的计算机体系结构选择最佳的内存移动方式——它应该快很多倍比你自己可以合理编写的任何代码。
关于制作它的列表然后删除然后回到数组的事情让我觉得是错误的。尚未测试,但我认为以下会表现更好。是的,我可能过度预优化。
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];
}
}
我意识到这是一个非常古老的帖子,但这里的一些答案帮助了我,所以这是我的 tuppence'ha'penny 的价值!
在我认为需要调整我正在写回的数组的大小之前,我努力让它工作了很长一段时间,除非对ArrayList
列表大小所做的更改保持不变。
如果ArrayList
您正在修改的最终元素比开始时更多或更少,则该行将List.toArray()
导致异常,因此您需要类似List.toArray(new String[] {})
orList.toArray(new String[0])
的东西来创建具有新(正确)大小的数组。
现在听起来很明显,我知道了。对于一个正在掌握新的和不熟悉的代码结构的 Android/Java 新手来说并不是那么明显,而且从这里的一些早期帖子中也不是很明显,所以只是想让其他人像我一样挠头几个小时来弄清楚这一点!
初始数组
int[] array = {5,6,51,4,3,2};
如果要删除索引 2 的 51,请使用以下
for(int i = 2; i < array.length -1; i++){
array[i] = array[i + 1];
}
编辑:
数组中具有空值的点已被清除。对不起我的评论。
原来的:
嗯……线
array = list.toArray(array);
用null替换已删除元素所在的数组中的所有间隙。这可能很危险,因为元素被删除,但数组的长度保持不变!
如果您想避免这种情况,请使用新数组作为 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));
没有留下任何空值。
我对这个问题的贡献不大。
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;
}
}
Arrgh,我无法正确显示代码。对不起,我让它工作了。再次抱歉,我认为我没有正确阅读问题。
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++;
}
}
这取决于您所说的“删除”是什么意思?数组是一个固定大小的结构 - 您不能更改其中的元素数量。因此,您可以 a) 创建一个新的、较短的数组,其中不包含您不想要的元素,或者 b) 将您不想要的条目分配给指示其“空”状态的东西;如果您不使用原语,通常为 null。
在第一种情况下,从数组中创建一个列表,删除元素,然后从列表中创建一个新数组。如果性能很重要,则遍历数组,将不应删除的任何元素分配给列表,然后从列表中创建一个新数组。在第二种情况下,只需通过并将 null 分配给数组条目。
将复制除索引为 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) );
}
如果元素的顺序无关紧要。您可以在元素 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
条目
在一个字符串数组中,如
String name = 'abcdeafbd e' // 可以像 String name = 'aa bb cde 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()
得到这个结果
abcdef
希望这段代码对任何人都有帮助
将 null 分配给数组位置。