views:

19163

answers:

14

Is there any fast (and nice looking) way to remove an element from an array in Java?

+14  A: 

You can't remove an element from the basic Java array. Take a look at various Collections and ArrayList instead.

Totophil
i know, i just want a beautiful looking way with arraylists or sth. like that, any hint for that?
Tobiask
+1: Use LinkedList, life is simpler.
S.Lott
LinkedList is rarely a good idea. The List intrrface gives you random access, but LinkedList gives O(n) access times instead of O(1).
Tom Hawtin - tackline
You can remove an element from an array via System.arrayCopy for example, but you cannot alter the size. A list is a much better solution however.
TofuBeer
@Tom: Whether LinkedList is the correct choice depends on other factors too. "Random access", i.e. accessing a linked list via an index, is O(n).
Todd Owen
+1 for getting to the crux of the problem - If the collection needs to vary dynmically in size then using an array is a bad choice.
Adamski
LinkedList depends on the usage. If I were implementing some kind of first in first out thing like a queue, I would use a Linked List. If I was inserting things all over the place or sorting a lot I might use a LinkedList. If I were implementing a stack (last in first out), or dealing with unsorted data, or needed random access, I would use an ArrayList. Generally I think ArrayList is the more useful of the two.
locka
A: 

Sure, create another array :)

Geo
+4  A: 

Nice looking solution would be to use a List instead of array in the first place.

List.remove(index)

If you have to use arrays, two calls to System.arraycopy will most likely be the fastest.

Foo[] result = new Foo[source.length - 1];
System.arraycopy(source, 0, result, 0, index);
if (source.length != index) {
    System.arraycopy(source, index + 1, result, index, source.length - index - 1);
}

(Arrays.asList is also a good candidate for working with arrays, but it doesn't seem to support remove.)

jelovirt
+1: Use LinkedList or ArrayList.
S.Lott
+1  A: 

Use an ArrayList:

alist.remove(1); //removes the element at position 1
Andreas Grech
A: 

I hope you use the java collection / java commons collections!

With an java.util.ArrayList you can do things like the following:

yourArrayList.remove(someObject);

yourArrayList.add(someObject);
Martin K.
An array is not a collection...
Nicolas
But the most collections are arrays! See: http://en.wikipedia.org/wiki/Array
Martin K.
Yep, but this question is java tagged and, in java, an array is not a collection...
Nicolas
I don't start to fight a religious war about what is a collection of elements and what isn't. Writing Java with a lot of procedural elements is bad! Take profit from the OO fatures! You can create nearly every collection from the Java Array construct.
Martin K.
I think we agree on it, but then the answer is either : why use collections instead of a raw array, or how to transfrom an array in a collection, not "you have an array, i explain how to do it with a collection"
Nicolas
In a "simple Java Array" you can set the pointer reference of the value in the array to "null" (and shift the other elements, maybe). That should be an answer.
Martin K.
Yes it could, if the array does not contains primitive types ;-)
Nicolas
Since Java offers autoboxing this should also be no problem?!
Martin K.
No: even with autoboxing, null value cannot be assigned to a primitive type. If you have an Integer[] tab, you can do tab[i] = null;if it's a int[] tab, you can't. There is no equivalent to null for primitive.
Nicolas
I don't see why this guy is being modded down. If you need to be able to easily remove an element from an ordered group, then it's pretty clear that perhaps an array is the wrong kind of group to use in the first place. So List is a good suggestion, and Set might be better, depending on the app.
Ben Hardy
A: 

Copy your original array into another array, without the element to be removed.

A simplier way to do that is to use a List, Set... and use the remove() method.

romaintaz
A: 

Swap the item to be removed with the last item, if resizing the array down is not an interest.

palindrom
This would break things if the array was sorted prior to the remove.
eleven81
A: 

okay, thx a lot now i use sth like this:

public static String[] removeElements(String[] input, String deleteMe) {
 if (input != null) {
  List<String> list = new ArrayList<String>(Arrays.asList(input));
  for (int i = 0; i < list.size(); i++) {
   if (list.get(i).equals(deleteMe)) {
    list.remove(i);
   }
  }
  return list.toArray(new String[0]);
 } else {
  return new String[0];
 }
}
Tobiask
If you really need to leave the inital array unchanged, you'd better create an empty list and fill it with the right elements rather than doing it this way.
Nicolas
I'm not sure this is what people had in mind when they suggested using collections, but at any rate, be careful with those list indices. It looks like you're skipping the element immediately following any removal (try {"a", "b", "deleteMe", "deleteMe", "c"}).
CapnNefarious
+6  A: 

You could use commons lang's ArrayUtils.

array = ArrayUtils.removeElement(array, element)

Javadocs

Peter Lawrey
+5  A: 

Wow, with about 10 answers here, nobody has come close to the right answer. I'm fairly stunned.

Do people just not know?

Anyway, this is the answer:

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#arraycopy(java.lang.Object, int, java.lang.Object, int, int)

Look at the docs. You can use it to copy from and to the same array at a slightly different offset.

So to delete the an element:

public void removeElement(Object[] a, int del) {
    arraycopy(a,del+1,a,del,a.length-1-del);
}

Edit in response to comment:

It's not another good way, it's really the only acceptable way.

To allocate a collection (creates a new array), then delete an element (which the collection will do using arraycopy) then call toArray on it (creates a SECOND new array) for every delete brings us to the point where it's not an optimizing issue, it's criminally bad programming.

Suppose you had an array taking up, say, 100mb of ram. Now you want to iterate over it and delete 20 elements.

Give it a try...

I know you ASSUME that it's not going to be that big, or that if you were deleting that many at once you'd code it differently, but I've fixed an awful lot of code where someone made assumptions like that.

Bill K
also a great idea!
Tobiask
Following a "deletion" (i.e. shifting the array left by one element) won't there be a duplicate of the end element? i.e. a.length will be the same following the deletion, no? I'm not saying I dislike the idea, just that one needs to be aware of this.
Adamski
+1. This works for my purposes. (I fixed the small issue you had in your sample. Hope you don't mind.)
Gunslinger47
Yes, this will just shift the elements left and there will be last element still present.We have to use new array to copy.
Reddy
BTW, this is what org.apache.commons.lang.ArrayUtils does too.
Reddy
+4  A: 

Your question isn't very clear. From your own answer, I can tell better what you are trying to do:

public static String[] removeElements(String[] input, String deleteMe) {
    List result = new LinkedList();

    for(String item : input)
        if(!deleteMe.equals(item))
            result.add(item);

    return result.toArray(input);
}

NB: This is untested. Error checking is left as an exercise to the reader (I'd throw IllegalArgumentException if either input or deleteMe is null; an empty list on null list input doesn't make sense. Removing null Strings from the array might make sense, but I'll leave that as an exercise too; currently, it will throw an NPE when it tries to call equals on deleteMe if deleteMe is null.)

Choices I made here:

I used a LinkedList. Iteration should be just as fast, and you avoid any resizes, or allocating too big of a list if you end up deleting lots of elements. You could use an ArrayList, and set the initial size to the length of input. It likely wouldn't make much of a difference.

Adam Jaskiewicz
+3  A: 

You could use the ArrayUtils API to remove it in a "nice looking way". It implements many operations (remove, find, add, contains,etc) on Arrays.
Take a look. It has made my life simpler.

Tom
+1  A: 

I think the question was asking for a solution without the use of the Collections API. One uses arrays either for low level details, where performance matters, or for a loosely coupled SOA integration. In the later, it is OK to convert them to Collections and pass them to the business logic as that.

For the low level performance stuff, it is usually already obfuscated by the quick-and-dirty imperative state-mingling by for loops, etc. In that case converting back and forth between Collections and arrays is cumbersome, unreadable, and even resource intensive.

By the way, TopCoder, anyone? Always those array parameters! So be prepared to be able to handle them when in the Arena.

Below is my interpretation of the problem, and a solution. It is different in functionality from both of the one given by Bill K and jelovirt. Also, it handles gracefully the case when the element is not in the array.

Hope that helps!

public char[] remove(char[] symbols, char c)
{
    for (int i = 0; i < symbols.length; i++)
    {
        if (symbols[i] == c)
        {
            char[] copy = new char[symbols.length-1];
            System.arraycopy(symbols, 0, copy, 0, i);
            System.arraycopy(symbols, i+1, copy, i, symbols.length-i-1);
            return copy;
        }
    }
    return symbols;
}
dadinn
This is working perfectly.
Reddy
A: 

Some more pre-conditions are needed for the ones written by Bill K and dadinn

Object[] newArray = new Object[src.length - 1];
if (i > 0)
{
    System.arraycopy(src, 0, newArray, 0, i);
}
if (newArray.length > i)
{
 System.arraycopy(src, i + 1, newArray, i, newArray.length - i);
}    
return newArray;
Binoy Joseph