How do I remove objects from an array in Java?

前端 未结 20 1399
Happy的楠姐
Happy的楠姐 2020-11-22 01:20

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]          


        
相关标签:
20条回答
  • 2020-11-22 01:46

    If you need to remove multiple elements from array without converting it to List nor creating additional array, you may do it in O(n) not dependent on count of items to remove.

    Here, a is initial array, int... r are distinct ordered indices (positions) of elements to remove:

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

    Small 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]
    

    In your task, you can first scan array to collect positions of "a", then call removeItems().

    0 讨论(0)
  • 2020-11-22 01:47

    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.

    0 讨论(0)
  • 2020-11-22 01:48

    I realise this is a very old post, but some of the answers here helped me out, so here's my tuppence' ha'penny's worth!

    I struggled getting this to work for quite a while before before twigging that the array that I'm writing back into needed to be resized, unless the changes made to the ArrayList leave the list size unchanged.

    If the ArrayList that you're modifying ends up with greater or fewer elements than it started with, the line List.toArray() will cause an exception, so you need something like List.toArray(new String[] {}) or List.toArray(new String[0]) in order to create an array with the new (correct) size.

    Sounds obvious now that I know it. Not so obvious to an Android/Java newbie who's getting to grips with new and unfamiliar code constructs and not obvious from some of the earlier posts here, so just wanted to make this point really clear for anybody else scratching their heads for hours like I was!

    0 讨论(0)
  • It depends on what you mean by "remove"? An array is a fixed size construct - you can't change the number of elements in it. So you can either a) create a new, shorter, array without the elements you don't want or b) assign the entries you don't want to something that indicates their 'empty' status; usually null if you are not working with primitives.

    In the first case create a List from the array, remove the elements, and create a new array from the list. If performance is important iterate over the array assigning any elements that shouldn't be removed to a list, and then create a new array from the list. In the second case simply go through and assign null to the array entries.

    0 讨论(0)
  • 2020-11-22 01:52

    Arrgh, I can't get the code to show up correctly. Sorry, I got it working. Sorry again, I don't think I read the question properly.

    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++;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:53

    Make a List out of the array with Arrays.asList(), and call remove() on all the appropriate elements. Then call toArray() on the 'List' to make back into an array again.

    Not terribly performant, but if you encapsulate it properly, you can always do something quicker later on.

    0 讨论(0)
提交回复
热议问题