如何从Java中删除数组中的对象?

时间:2008-09-21 23:16:27

标签: java arrays data-structures data-manipulation

给定一组 n 对象,假设它是一个字符串数组,它具有以下值:

foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";

如何删除/删除数组中等于“a”的所有字符串/对象?

22 个答案:

答案 0 :(得分:104)

[如果你想要一些现成的代码,请滚动到我的“Edit3”(剪辑后)。剩下的就是后人。]

充实Dustman's idea

List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);

编辑:我现在使用的是Arrays.asList而不是Collections.singleton:单例限制为一个条目,而asList方法允许您添加其他字符串以便稍后过滤:{ {1}}。

Edit2:上面的方法保留了相同的数组(所以数组的长度仍然相同);最后一个元素设置为null。如果您希望 new 数组的大小完全符合要求,请改为使用:

Arrays.asList("a", "b", "c")

编辑3:如果您经常在同一个班级中使用此代码,您可以考虑将其添加到您的班级:

array = list.toArray(new String[0]);

然后该功能变为:

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()]); )。

答案 1 :(得分:27)

Java 8中的替代方案:

String[] filteredArray = Arrays.stream(array)
    .filter(e -> !e.equals(foo)).toArray(String[]::new);

答案 2 :(得分:20)

使用List从数组中取出Arrays.asList(),并在所有相应元素上调用remove()。然后在“列表”上调用toArray()以重新生成数组。

性能不是很高,但如果你正确地封装它,你总是可以在以后更快地做一些事情。

答案 3 :(得分:15)

你总是可以这样做:

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);

答案 4 :(得分:6)

您可以使用外部库:

org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)

项目是Apache Commons Lang http://commons.apache.org/lang/

答案 5 :(得分:5)

见下面的代码

ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);

答案 6 :(得分:4)

如果您需要从数组中删除多个元素而不将其转换为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()

答案 7 :(得分:3)

关于make的列表然后删除然后回到数组​​会让我觉得错误。没有测试过,但我认为以下内容会更好。是的,我可能过度地进行了优化。

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];
   }
}

答案 8 :(得分:2)

我意识到这是一个非常古老的帖子,但是这里的一些答案帮助了我,所以这里是我的贪财'ha'penny的价值!

我努力让这个工作了很长一段时间之前,我正在写回的数组需要调整大小,除非对ArrayList所做的更改使列表大小保持不变。

如果您要修改的ArrayList结尾的元素数量多于或少于开头数,则行List.toArray()会导致异常,因此您需要List.toArray(new String[] {})List.toArray(new String[0])以创建具有新(正确)大小的数组。

现在我明白了,这听起来很明显。 Android / Java新手不是那么明显,他们正在处理新的和不熟悉的代码结构,而且这里的一些早期帖子并不明显,所以只是想让这一点真正清楚,让任何人像我一样搔头几个小时!

答案 9 :(得分:2)

这里有很多答案 - 我看到的问题是你没有说明你为什么使用数组而不是集合,所以让我提出一些理由以及哪些解决方案适用(大多数解决方案已在其他问题中得到解答,因此我不会详细介绍):

原因:您不知道收藏包存在或不信任

解决方案:使用集合。

如果您打算从中间添加/删除,请使用LinkedList。如果您真的担心大小或经常索引到集合的中间,请使用ArrayList。这两个都应该有删除操作。

原因:您关注大小或想要控制内存分配

解决方案:使用具有特定初始大小的ArrayList。

ArrayList只是一个可以自行扩展的数组,但它并不总是需要这样做。添加/删除项目非常聪明,但如果从中间插入/删除LOT,请再次使用LinkedList。

原因:你有一个阵列进入阵列并且阵列外出 - 所以你想要在阵列上操作

解决方案:将其转换为ArrayList,删除该项并将其转换回来

原因:如果你自己做的话,你认为你可以编写更好的代码

解决方案:您不能使用数组或链接列表。

原因:这是一项课程作业,您不被允许或由于某种原因您无法访问该集合apis

假设:您需要新数组是正确的&#34;大小&#34;

溶液: 扫描阵列以查找匹配的项目并对其进行计数。创建一个正确大小的新数组(原始大小 - 匹配数)。重复使用System.arraycopy将要保留的每组项目复制到新阵列中。如果这是一个课堂作业并且你不能使用System.arraycopy,那么只需一次一个地复制它们一个循环但是不要在生产代码中这样做,因为它要慢得多。 (这些解决方案都在其他答案中详述)

原因:你需要运行裸机

假设:你不必不必要地分配空间或花费太长时间

假设:您正在分别跟踪数组中使用的大小(长度),否则您必须重新分配数组以进行删除/插入。

为什么你可能想要这样做的一个例子:单个基元数组(让我们说int值)占据你公羊的很大一部分 - 比如50%! ArrayList会强制它们进入一个指向Integer对象的指针列表,这些指针会使用少量的内存。

解决方案:迭代您的数组,每当您找到要删除的元素时(让它将其称为元素n),使用System.arraycopy将数组的尾部复制到&#34;已删除的&#34; element(Source和Destination是相同的数组) - 它足够聪明,可以按正确的方向进行复制,因此内存不会覆盖自身:

 System.arraycopy(ary, n+1, ary, n, length-n) 
 length--;

如果您一次删除多个元素,您可能希望比这更聪明。你只能在一个&#34;匹配&#34;之间移动该区域。和下一个而不是整个尾巴一如既往地避免移动任何块两次。

在最后一种情况下,你绝对必须自己完成这项工作,并且使用System.arraycopy实际上是唯一的方法,因为它会选择最好的方式为你的计算机架构移动内存 - - 它应该比你自己合理写的代码快很多倍。

答案 10 :(得分: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));

没有留下任何空值。

答案 11 :(得分:1)

我对这个问题的贡献很少。

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;
}

}

答案 12 :(得分:1)

初始数组

   int[] array = {5,6,51,4,3,2};

如果要删除索引2的51,请使用以下

 for(int i = 2; i < array.length -1; i++){
    array[i] = array[i + 1];
  }

答案 13 :(得分:0)

仅删除多个相同条目中​​的第一个
带有 lambda

boolean[] done = {false};
String[] arr = Arrays.stream( foo ).filter( e ->
  ! (! done[0] && Objects.equals( e, item ) && (done[0] = true) ))
    .toArray(String[]::new);

可以删除 null 个条目

答案 14 :(得分:0)

如果元素的顺序无关紧要。您可以在元素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);
}

答案 15 :(得分:0)

在像这样的字符串数组中

字符串名称='a b c d e a f b d e'//可能像字符串名称='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

希望此代码可以帮助任何人 问候

答案 16 :(得分:0)

将复制除索引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) );
            }

答案 17 :(得分:0)

这取决于“删除”的含义?数组是固定大小的构造 - 您无法更改其中的元素数。因此,您可以a)创建一个新的,更短的数组,而不使用您不想要的元素,或者b)将您不想要的条目分配给表示其“空”状态的内容;如果你不使用原语,通常为null。

在第一种情况下,从数组中创建一个List,删除元素,然后从列表中创建一个新数组。如果性能很重要,则迭代数组,将任何不应删除的元素分配给列表,然后从列表中创建新数组。在第二种情况下,只需通过并为数组条目赋值null。

答案 18 :(得分:0)

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++;
    }
}

答案 19 :(得分:-3)

使用:

list.removeAll(...);
//post what char you need in the ... section

答案 20 :(得分:-3)

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.

答案 21 :(得分:-7)

将null分配给数组位置。