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

java arrays data-structures data-manipulation

341442 просмотра

21 ответа

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

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

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

Автор: ramayac Источник Размещён: 06.08.2019 10:52

Ответы (21)


103 плюса

Решение

[Если вам нужен готовый код, перейдите к моему «Edit3» (после вырезки). Остальное здесь для потомков.]

Чтобы реализовать идею Дастмена :

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

Изменить: Я сейчас , используя Arrays.asListвместо Collections.singleton: одноточечного ограничивается одной записи, в то время как asListподход позволяет добавить другие строки , чтобы отфильтровать позднее: Arrays.asList("a", "b", "c").

Edit2: вышеупомянутый подход сохраняет тот же массив (таким образом, массив все еще той же длины); элемент после последнего установлен в нуль. Если вы хотите, чтобы новый массив был точно такого же размера, используйте его:

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каждом вызове вашей функции.

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

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

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

Автор: Chris Jester-Young Размещён: 21.09.2008 11:30

27 плюса

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

String[] filteredArray = Arrays.stream(array)
    .filter(e -> !e.equals(foo)).toArray(String[]::new);
Автор: Vitalii Fedorenko Размещён: 20.04.2014 11:44

20 плюса

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

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

Автор: Dustman Размещён: 21.09.2008 11:18

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);
Автор: anon Размещён: 23.09.2008 06:55

6 плюса

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

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

Он находится в проекте Apache Commons Lang http://commons.apache.org/lang/

Автор: bugs_ Размещён: 04.02.2011 02:41

5 плюса

Смотрите код ниже

ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);
Автор: Ali Размещён: 26.01.2014 08:37

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]

В вашей задаче вы можете сначала отсканировать массив, чтобы собрать позиции «а», а затем вызвать removeItems().

Автор: Alex Salauyou Размещён: 10.05.2015 12:12

3 плюса

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

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];
   }
}
Автор: shsteimer Размещён: 22.09.2008 12:50

2 плюса

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

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

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

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

Автор: DDSports Размещён: 05.07.2013 11:49

2 плюса

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

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

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

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

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

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

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

причина: у вас есть входящий массив и выходящий массив - поэтому вы хотите работать с массивом

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

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

Решение: вы не можете использовать массив или связанный список.

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

допущение: новый массив должен иметь правильный размер

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

причина: нужно бегать голым металлом

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

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

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

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

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

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

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

Автор: Bill K Размещён: 24.05.2017 05:10

1 плюс

РЕДАКТИРОВАТЬ:

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

Оригинал:

Эмм ... линия

array = list.toArray(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]

Где в качестве текущего принятого ответа Крис Йестер Янг выводов:

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

без каких-либо нулевых значений.

Автор: GHad Размещён: 22.09.2008 08:20

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

}

Автор: Andre Размещён: 30.11.2013 01:52

1 плюс

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

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

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

 for(int i = 2; i < array.length -1; i++){
    array[i] = array[i + 1];
  }
Автор: Ebin Joy Размещён: 19.11.2018 09:47

0 плюса

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

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

Автор: DJClayworth Размещён: 24.09.2008 09:15

0 плюса

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

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++;
    }
}
Автор: AngelOfCake Размещён: 22.09.2008 12:59

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) );
            }
Автор: PauLy Размещён: 11.06.2016 07:00

0 плюса

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

String name = 'abcdeafbde' // может быть похож на String name = 'aa bb cde aa f bb de'

Я строю следующий класс

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

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

Автор: Orlando Reyes Размещён: 18.06.2019 03:40

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);
}
Автор: milevyo Размещён: 06.08.2019 07:44

-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.
Автор: Parameshwar Размещён: 29.07.2015 02:59

-3 плюса

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

list.removeAll(...);
//post what char you need in the ... section
Автор: LOL Размещён: 05.12.2015 02:38

-7 плюса

Присвойте null местоположениям массива.

Автор: alfinoba Размещён: 21.09.2008 11:19
Вопросы из категории :
32x32