Как удалить объекты из массива в Java?

Учитывая массив объектов n, скажем, это массив строк, и он имеет следующие значения:

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

Что мне нужно сделать, чтобы удалить/удалить все строки/объекты, равные "a" в массиве?

Ответ 1

[Если вы хотите получить готовый к использованию код, прокрутите страницу до "Edit3" (после вырезания). Остальное здесь для потомков.]

Извлечь Идею Dustman:

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

Изменить: теперь я использую Arrays.asList вместо Collections.singleton: 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 ed при каждом вызове функции.

cynicalman suggestion (см. комментарии) также поможет с завалением кучи, и для справедливости я должен упомянуть это:

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

Я предпочитаю свой подход, потому что может быть проще получить явный размер неправильно (например, вызывать size() в неправильном списке).

Ответ 2

Альтернатива в Java 8:

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

Ответ 3

Сделайте List из массива с Arrays.asList() и вызовите remove() для всех соответствующих элементов. Затем вызовите toArray() в "List", чтобы снова вернуться в массив.

Не очень впечатляюще, но если вы инкапсулируете его правильно, вы всегда можете сделать что-то более быстрое.

Ответ 4

Вы всегда можете сделать:

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

Ответ 5

Вы можете использовать внешнюю библиотеку:

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

Это в проекте Apache Commons Lang http://commons.apache.org/lang/

Ответ 6

См. код ниже

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

Ответ 7

Если вам нужно удалить несколько элементов из массива без преобразования его в 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().

Ответ 8

Что-то о том, чтобы сделать список, а затем удалить, а затем вернуться к массиву, кажется мне неправильным. Не тестировали, но я думаю, что следующее будет работать лучше. Да, я, вероятно, необоснованно заранее оптимизирую.

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

Ответ 9

Я понимаю, что это очень старый пост, но некоторые из ответов здесь помогли мне, так что здесь моя баснословная ценность!

Я изо всех сил пытался заставить это работать некоторое время до того, как до твиггировать, что массив, который я пишу обратно, нуждается в изменении размера, если изменения, сделанные в ArrayList, не изменяют размер списка.

Если параметр ArrayList, который вы изменяете, заканчивается большим или меньшим количеством элементов, чем он начинался, строка List.toArray() вызывает исключение, поэтому вам нужно что-то вроде List.toArray(new String[] {}) или List.toArray(new String[0]), чтобы создайте массив с новым (правильным) размером.

Теперь звучит очевидно, что я это знаю. Не так очевидно для новичка Android/Java, который справляется с новыми и незнакомыми конструкциями кода и не очевиден из некоторых более ранних сообщений здесь, поэтому просто хотел, чтобы этот пункт был действительно понятен для кого-то еще, царапающего их головы часами, как я был

Ответ 10

Здесь много ответов - проблема в том, что вы не сказали, ПОЧЕМУ вы используете массив вместо коллекции, поэтому позвольте мне предложить пару причин и какие решения будут применяться (Most о решениях уже были даны ответы на другие вопросы здесь, поэтому я не буду вдаваться в подробности):

причина: вы не знали, что пакет коллекции существует или не доверял ему

Решение: используйте коллекцию.

Если вы планируете добавлять/удалять из середины, используйте LinkedList. Если вы действительно обеспокоены размером или часто индексируете прямо в середину коллекции, используйте ArrayList. Обе из них должны иметь операции удаления.

причина: вы обеспокоены размером или хотите контролировать распределение памяти

: используйте ArrayList с определенным начальным размером.

ArrayList - это просто массив, который может расширяться, но это не всегда нужно делать. Будет очень полезно добавлять/удалять элементы, но опять же, если вы вставляете/удаляете LOT из середины, используйте LinkedList.

причина: у вас есть массив, в который входит массив, и вы хотите работать с массивом

: преобразовать его в ArrayList, удалить элемент и преобразовать его

причина: вы думаете, что можете написать лучший код, если вы сделаете это самостоятельно

: вы не можете использовать список Array или Linked.

причина: это назначение класса, и вы не разрешены или у вас нет доступа к коллекции apis по какой-либо причине

Предположение: новый массив должен быть правильным "размером"

решение: Сканирование массива для сопоставления элементов и подсчета их. Создайте новый массив правильного размера (исходный размер - количество совпадений). используйте System.arraycopy для копирования каждой группы элементов, которые вы хотите сохранить в новом массиве. Если это назначение класса, и вы не можете использовать System.arraycopy, просто скопируйте их по одному вручную в цикле, но никогда не делайте этого в производственном коде, потому что он намного медленнее. (Эти решения подробно описаны в других ответах)

причина: вам нужно запустить bare metal

: вы НЕ ДОЛЖНЫ распределять пространство без необходимости или слишком долго

Предположение: вы отслеживаете размер, используемый в массиве (длина) отдельно, потому что в противном случае вам придется перераспределять ваш массив для удаления/вставки.

Пример того, почему вы, возможно, захотите сделать это: один массив примитивов (Let say int values) занимает значительную часть вашего барана - например, 50%! ArrayList заставит их перечислить указатели на объекты Integer, которые будут использовать несколько раз этот объем памяти.

: Итерируйте по вашему массиву и всякий раз, когда вы обнаружите элемент для удаления (пусть его вызывает элемент n), используйте System.arraycopy для копирования хвоста массива над "удаленным" элементом (Source и Destination - это тот же массив) - Это достаточно умно, чтобы сделать копию в правильном направлении, чтобы память не перезаписывала себя:

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

Вероятно, вы захотите стать более умным, если вы удалите более одного элемента за раз. Вы только перемещали бы область между одним "совпадением" и следующим, а не всем хвостом, и, как всегда, избегайте перемещать любой фрагмент дважды.

В этом последнем случае вы абсолютно должны сами выполнить эту работу, и использование System.arraycopy - это единственный способ сделать это, поскольку он собирается выбрать наилучший возможный способ перемещения памяти для вашей компьютерной архитектуры - это должно быть во много раз быстрее, чем любой код, который вы могли бы разумно написать себе.

Ответ 11

EDIT:

Точка с нулями в массиве очищена. Извините за мои комментарии.

Оригинал:

Ehm... строка

array = list.toArray(array);

заменяет все пробелы в массиве, где удаленный элемент был с null. Это может быть опасно, поскольку элементы удаляются, но длина массива остается неизменной!

Если вы хотите этого избежать, используйте новый параметр Array для параметра 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));

без оставленных нулевых значений.

Ответ 12

Мой маленький вклад в эту проблему.

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

}

Ответ 13

Начальный массив

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

если вы хотите удалить 51, который является индексом 2, используйте следующее

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

Ответ 14

Астро, я не могу правильно отобразить код. Извините, я заработал. Извините, я не думаю, что правильно прочитал вопрос.

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

Ответ 15

Это зависит от того, что вы подразумеваете под "удалением"? Массив - это конструкция с фиксированным размером - вы не можете изменить количество элементов в нем. Таким образом, вы можете: a) создать новый, более короткий массив без элементов, которые вам не нужны, или b) назначить записи, которые вы не хотите, чтобы указать их "пустой" статус; обычно null, если вы не работаете с примитивами.

В первом случае создайте список из массива, удалите его и создайте новый массив из списка. Если производительность важна, перебирайте массив, назначая любые элементы, которые не следует удалять в список, а затем создайте новый массив из списка. Во втором случае просто перейдите и присвойте значение NULL элементам.

Ответ 16

Скопирует все элементы, кроме одного с индексом 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

В массиве строк, как

String name = 'abcdeafbde'//может быть похож на 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

надеюсь, что этот код поможет кому-либо С уважением

Ответ 18

Если это не имеет значения, порядок элементов. вы можете переключаться между элементами 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);
}

Ответ 19

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.

Ответ 20

Использование:

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

Ответ 21

Назначьте нуль ячейкам массива.