2012-03-29 18 views
13

Naprawiłem to właściwie. Oto mój nowy kod.Odejmowanie jednej arrayList od innej arrayList

//returns a new IntSet after subtracting a from b 
// .minus().toString() 
ArrayList<Integer> minusArray = new ArrayList<Integer>(); 

    minusArray.addAll(array1); 

    for(int i =0; i< minusArray.size(); i++){ 
     for(int j = 0; j < array2.size(); j++){ 
      if(minusArray.get(i).equals(array2.get(j))){ 
       minusArray.remove(i); 
       if(i == 0){ 
        ; 
       } 
       else if(j == 0){ 
        ; 
       } 
       else{ 
        i = 0; 
        j = 0; 
       } 
      } 
      else{} 
     } 
    } 

return minusArray; 

Mam dwa arrayLists i staram się "odjąć" jeden ArrayList od drugiego. Na przykład, jeśli mam jedną tablicęList [1,2,3] i próbuję odjąć [0, 2, 4], wynikowa tablicaList powinna być [1,3].

Mój kod działa w niektórych przypadkach, np. Jeśli arrayList1 = [4,6] i arrayList2 = [6] to da mi wynik [4]. Ale gdy próbuję coś jak [1,2,4] i [0,4,8]

otrzymuję ten wyjątek:

java.lang.IndexOutOfBoundsException: Index: 2, Size: 2 
    at java.util.ArrayList.rangeCheck(Unknown Source) 
    at java.util.ArrayList.get(Unknown Source) 
    at IntSet.minus(IntSet.java:119) 
    at IntSetDriver.main(IntSetDriver.java:62) 

Oto kod mam wymyślić. Przeprowadziłem testy przez to i dla mnie myślę, że to powinno działać. Użytkownik wprowadza te arrayLists i są one sortowane, ja też nie wiem, Hash lub big-O.

ArrayList<Integer> minusArray = new ArrayList<Integer>(); 

    minusArray.addAll(array1); 

    for(int i =0; i< minusArray.size(); i++){ 
     for(int j = 0; j < array2.size(); j++){ 
      if(minusArray.get(i).equals(array2.get(j))){ 
       minusArray.remove(i); 
      } 
      else{} 
     } 
    } 

return minusArray; 

Odpowiedz

2

Twoim problemem jest to, że w swojej minusArray.remove (...) nazwać można zmniejszyć rozmiar minusArray. Aby to naprawić, zacznij od array.size() - 1 i odliczaj wstecz do 0

Sprawdź, czy nawet to nie naprawi. Musisz odwrócić kolejność swoich pętli

28

Spróbuj użyć metody odejmowania klasy org.apache.commons.collections.CollectionUtils.

Zwraca nową kolekcję zawierającą a - b. Liczność każdego elementu e w zwróconym zbiorze będzie licznością e in a minus liczebność e in b lub zero, w zależności od tego, która wartość jest większa.

CollectionUtils.subtract (java.util.Collection a, java.util.Collection b)

Od Apache Commons Collections

+0

Co to jest CS 251? – kukis

+2

@kukis CS 251 będzie drugim rokiem studiów informatycznych na uniwersytecie. –

2

Zgaduję masz problem, ponieważ zakres Usunęliśmy jeden z elementów która zmienia to, czego szuka wewnętrzna pętla (wiem, że ten problem występuje w przypadku normalnych list i kolekcji).

To, co musiałem zrobić w przeszłości, aby obejść ten problem, to stworzyć listę przedmiotów, które należy usunąć (czyli te, które można znaleźć na oryginalnej liście). Przejrzyj tę nową listę i bezpośrednio usuń elementy pierwotnej listy bez konieczności przechodzenia przez iterator.

6

przejechanie minusArray za pomocą indeksu jest jednym ze sposobów, aby to zrobić, ale proponuję skorzystać z metody contains(Object), która pozwoli Ci wtedy korzystać remove(Object) dla danego elementu array2.

Oczywiście, zawsze istnieje removeAll(Collection) która robi prawie wszystko, czego potrzeba ...

+0

+1 za "normalny" sposób, aby to zrobić. –

4

Można użyć org.apache.commons.collections.ListUtils i zrobić wszystko, co chcesz, tylko w jednym wierszu =)

List resultList = ListUtils.subtract(list, list2); 
22

Czy istnieje jakiś powód, dla którego nie można po prostu użyć List.removeAll (List)?

List<Integer> one = new ArrayList<Integer>(); 
    one.add(1); 
    one.add(2); 
    one.add(3); 
    List<Integer> two = new ArrayList<Integer>(); 
    two.add(0); 
    two.add(2); 
    two.add(4); 
    one.removeAll(two); 
    System.out.println(one); 

    result: "[1, 3]"