How do I remove objects from an array in Java?

2018-12-31 05:23发布

Given an array of n Objects, let's say it is an array of strings, and it has the following values:

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

What do I have to do to delete/remove all the strings/objects equal to "a" in the array?

19条回答
笑指拈花
2楼-- · 2018-12-31 05:34

An alternative in Java 8:

String[] filteredArray = Arrays.stream(array)
    .filter(e -> !e.equals(foo)).toArray(String[]::new);
查看更多
深知你不懂我心
3楼-- · 2018-12-31 05:34

Will copy all elements except the one with index 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) );
            }
查看更多
深知你不懂我心
4楼-- · 2018-12-31 05:35

Something about the make a list of it then remove then back to an array strikes me as wrong. Haven't tested, but I think the following will perform better. Yes I'm probably unduly pre-optimizing.

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];
   }
}
查看更多
弹指情弦暗扣
5楼-- · 2018-12-31 05:39

[If you want some ready-to-use code, please scroll to my "Edit3" (after the cut). The rest is here for posterity.]

To flesh out Dustman's idea:

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

Edit: I'm now using Arrays.asList instead of Collections.singleton: singleton is limited to one entry, whereas the asList approach allows you to add other strings to filter out later: Arrays.asList("a", "b", "c").

Edit2: The above approach retains the same array (so the array is still the same length); the element after the last is set to null. If you want a new array sized exactly as required, use this instead:

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

Edit3: If you use this code on a frequent basis in the same class, you may wish to consider adding this to your class:

private static final String[] EMPTY_STRING_ARRAY = new String[0];

Then the function becomes:

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

This will then stop littering your heap with useless empty string arrays that would otherwise be newed each time your function is called.

cynicalman's suggestion (see comments) will also help with the heap littering, and for fairness I should mention it:

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

I prefer my approach, because it may be easier to get the explicit size wrong (e.g., calling size() on the wrong list).

查看更多
墨雨无痕
6楼-- · 2018-12-31 05:40

EDIT:

The point with the nulls in the array has been cleared. Sorry for my comments.

Original:

Ehm... the line

array = list.toArray(array);

replaces all gaps in the array where the removed element has been with null. This might be dangerous, because the elements are removed, but the length of the array remains the same!

If you want to avoid this, use a new Array as parameter for toArray(). If you don`t want to use removeAll, a Set would be an alternative:

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

Gives:

[a, bc, dc, a, ef]
[dc, ef, bc]

Where as the current accepted answer from Chris Yester Young outputs:

[a, bc, dc, a, ef]
[bc, dc, ef, null, ef]

with the code

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

without any null values left behind.

查看更多
时光乱了年华
7楼-- · 2018-12-31 05:42

There are a lot of answers here--the problem as I see it is that you didn't say WHY you are using an array instead of a collection, so let me suggest a couple reasons and which solutions would apply (Most of the solutions have already been answered in other questions here, so I won't go into too much detail):

reason: You didn't know the collection package existed or didn't trust it

solution: Use a collection.

If you plan on adding/deleting from the middle, use a LinkedList. If you are really worried about size or often index right into the middle of the collection use an ArrayList. Both of these should have delete operations.

reason: You are concerned about size or want control over memory allocation

solution: Use an ArrayList with a specific initial size.

An ArrayList is simply an array that can expand itself, but it doesn't always need to do so. It will be very smart about adding/removing items, but again if you are inserting/removing a LOT from the middle, use a LinkedList.

reason: You have an array coming in and an array going out--so you want to operate on an array

solution: Convert it to an ArrayList, delete the item and convert it back

reason: You think you can write better code if you do it yourself

solution: you can't, use an Array or Linked list.

reason: this is a class assignment and you are not allowed or you do not have access to the collection apis for some reason

assumption: You need the new array to be the correct "size"

solution: Scan the array for matching items and count them. Create a new array of the correct size (original size - number of matches). use System.arraycopy repeatedly to copy each group of items you wish to retain into your new Array. If this is a class assignment and you can't use System.arraycopy, just copy them one at a time by hand in a loop but don't ever do this in production code because it's much slower. (These solutions are both detailed in other answers)

reason: you need to run bare metal

assumption: you MUST not allocate space unnecessarily or take too long

assumption: You are tracking the size used in the array (length) separately because otherwise you'd have to reallocate your array for deletes/inserts.

An example of why you might want to do this: a single array of primitives (Let's say int values) is taking a significant chunk of your ram--like 50%! An ArrayList would force these into a list of pointers to Integer objects which would use a few times that amount of memory.

solution: Iterate over your array and whenever you find an element to remove (let's call it element n), use System.arraycopy to copy the tail of the array over the "deleted" element (Source and Destination are same array)--it is smart enough to do the copy in the correct direction so the memory doesn't overwrite itself:

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

You'll probably want to be smarter than this if you are deleting more than one element at a time. You would only move the area between one "match" and the next rather than the entire tail and as always, avoid moving any chunk twice.

In this last case, you absolutely must do the work yourself, and using System.arraycopy is really the only way to do it since it's going to choose the best possibly way to move memory for your computer architecture--it should be many times faster than any code you could reasonably write yourself.

查看更多
登录 后发表回答