CodeGym/Java Blog/무작위의/ArrayList에서 요소 삭제
John Squirrels
레벨 41
San Francisco

ArrayList에서 요소 삭제

무작위의 그룹에 게시되었습니다
회원
안녕! 지난 수업에서 우리는 클래스에 대해 알게 되었고 ArrayList이 클래스로 가장 일반적인 작업을 수행하는 방법을 배웠습니다. 또한 an ArrayList과 일반 배열의 몇 가지 차이점을 지적했습니다. 그러나 우리는 한 가지 주제 , ArrayList . 지금 논의하겠습니다. ArrayList에서 요소 삭제 - 1일반 배열에서 요소를 삭제하는 것이 그다지 편리하지 않다고 이미 언급했습니다. 요소 자체를 삭제할 수 없기 때문에 값을 "제로아웃"(null로 설정)할 수만 있습니다.
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;

       System.out.println(Arrays.toString(cats));
   }


@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
출력: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] 그러나 배열 요소를 null로 설정하면 "구멍"이 생깁니다. 배열에서 위치를 제거하지 않고 해당 내용만 제거했습니다. 50마리의 고양이 배열이 있고 그 중 17마리를 이런 식으로 제거하면 어떤 일이 일어날지 상상해 보십시오. 우리는 17개의 구멍을 가진 배열을 갖게 될 것입니다. 계속 추적해 보세요! 새 값을 쓸 수 있는 빈 셀의 수를 기억하는 것은 비현실적입니다. 한 가지 실수를 하면 원하는 개체 참조를 덮어쓰게 됩니다. 물론 이를 좀 더 신중하게 수행하는 방법이 있습니다. 요소를 제거한 후 요소를 배열의 맨 앞으로 이동하여 끝에 "구멍"을 넣습니다.
public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Behemoth");
   cats[2] = new Cat("Lionel Messi");
   cats[2] = new Cat("Fluffy");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       cats [i-1] = cats [i];// Move the elements to the front of the array, so the empty position is at the end
   }

   System.out.println(Arrays.toString(cats));
}
출력: [Cat{name='Thomas'}, Cat{name='Fluffy'}, Cat{name='Fluffy'}, null] 이것은 더 좋아 보이지만 강력한 솔루션이라고 할 수는 없습니다. 배열에서 요소를 삭제할 때마다 이 코드를 작성해야 한다는 사실 외에 다른 이유가 없다면! 이것은 나쁜 선택입니다. 다른 방법으로 별도의 메서드를 만들 수 있습니다.
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...delete the cat corresponding to the index and move the elements
}
그러나 이것은 거의 사용되지 않습니다. 이 방법은 객체 에만 사용할 수 Cat있고 다른 유형에는 사용할 수 없습니다. 즉, 프로그램에 배열과 함께 사용하려는 또 다른 100개의 클래스가 있는 경우 각 클래스에서 정확히 동일한 논리로 동일한 메서드를 작성해야 합니다. 이것은 완전히 재앙입니다 -_- 하지만 ArrayList클래스는 이 문제를 해결합니다! 요소를 제거하기 위한 특수 메서드를 구현합니다.remove()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
객체의 인덱스를 메서드에 전달하면 객체를 삭제합니다(배열에서처럼). 이 remove()방법에는 두 가지 특별한 기능이 있습니다. 첫째, "구멍"을 남기지 않습니다. 이전에 직접 작성한 요소가 중간에서 제거될 때 요소를 이동하는 데 필요한 논리를 이미 구현합니다 . 이전 코드의 출력을 살펴보십시오.
[Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]

[Cat{name='Thomas'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
가운데 고양이 한 마리를 빼고 나머지는 빈 공간이 없도록 옮겼습니다. 둘째 , 인덱스(일반 배열과 같음)뿐만 아니라 참조로 도 객체를 삭제할 수 있습니다 .
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(lionel);

   System.out.println(cats.toString());
}
출력: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] 원하는 개체의 인덱스를 항상 추적하고 싶지 않은 경우 매우 편리할 수 있습니다. 일반적인 삭제 방법을 알아낸 것 같습니다. 이제 이 상황을 상상해 봅시다. 목록을 반복하고 특정 이름을 가진 고양이를 제거하려고 합니다 . for이를 위해 Rishi의 수업에서 소개한 빠른 루프(for-each 루프라고도 함)를 사용합니다 .
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   for (Cat cat: cats) {

       if (cat.name.equals("Behemoth")) {
           cats.remove(cat);
       }
   }

   System.out.println(cats);
}
코드는 완벽하게 논리적으로 보입니다. 그러나 그 결과는 매우 놀랍습니다. java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)의 java.util.ArrayList$Itr.next(ArrayList. java:831) at Cat.main(Cat.java:25) 일종의 오류가 있으며 발생한 이유가 명확하지 않습니다. 이 프로세스에는 해결해야 하는 여러 가지 뉘앙스가 포함됩니다. 기억해야 할 일반적인 규칙은 다음과 같습니다. 컬렉션을 반복하면서 동시에 해당 요소를 변경할 수 없습니다. 그리고 우리는 단순히 제거가 아니라 모든 종류의 변화를 의미합니다. 고양이 제거를 새 고양이를 삽입하려는 시도로 바꾸면 결과는 동일합니다.
for (Cat cat: cats) {

   cats.add(new Cat("Salem Saberhagen"));
}

System.out.println(cats);
"main" 스레드의 예외 java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) at java.util.ArrayList$Itr.next(ArrayList.java:831) at Cat.main( Cat.java:25) 하나의 작업을 다른 작업으로 변경했지만 결과는 변경되지 않았습니다. 동일한 ConcurrentModificationException 이 발생합니다 . 목록을 반복하는 동안 목록을 변경하여 위의 규칙을 어기려고 할 때 정확하게 발생합니다. Java에서는컬렉션을 반복하는 동안 항목을 삭제하기 위해 iterator (Iterator클래스Iterator는 요소 목록을 안전하게 반복할 책임이 있습니다. 3가지 방법만 있기 때문에 매우 간단합니다.
  • hasNext()- 목록에 다음 항목이 있는지 또는 이미 마지막 항목에 도달했는지 여부에 따라 true 또는 false를 반환합니다.
  • next()- 목록의 다음 항목을 반환합니다.
  • remove()- 목록에서 항목을 제거합니다.
보시다시피 이터레이터는 우리의 필요에 맞게 맞춤 제작되었으며 동시에 복잡하지 않습니다. 목록에 다음 요소가 있는지 확인하고 다음 요소가 있으면 표시한다고 가정합니다.
Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list

   Cat nextCat = catIterator.next();// Get the next element
   System.out.println(nextCat);// Display it
}
출력: Cat{name='Thomas'} Cat{name='Behemoth'} Cat{name='Lionel Messi'} Cat{name='Fluffy'} 보시다시피,ArrayList이미 반복자: iterator(). 또한 반복자를 만들 때 작업할 개체의 클래스를 지정합니다( <Cat>). 핵심은 반복자가 원래 작업을 쉽게 처리한다는 것입니다. 예를 들어 "Lionel Messi"라는 이름의 고양이를 제거합니다.
Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list

   Cat nextCat = catIterator.next();// Get the next element
   if (nextCat.name.equals("Lionel Messi")) {
       catIterator.remove();// Delete the cat with the specified name
   }
}

System.out.println(cats);
출력: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}]remove() 반복자의 메서드 에서 인덱스나 이름을 지정하지 않은 것을 눈치채셨을 것입니다. ! 반복자는 보이는 것보다 더 똑똑합니다. remove()반복자가 반환한 마지막 요소를 제거합니다. 보시다시피, 우리가 원하는 대로 작동했습니다. :) 원칙적으로 에서 요소를 제거하는 방법에 대해 알아야 할 모든 것입니다 ArrayList. 글쎄, 거의 모든 것. 다음 강의에서는 이 클래스 내부를 살펴보고 다양한 메서드 호출 중에 어떤 일이 발생하는지 살펴보겠습니다 :) 그때까지!
코멘트
  • 인기
  • 신규
  • 이전
코멘트를 남기려면 로그인 해야 합니다
이 페이지에는 아직 코멘트가 없습니다