2011-12-08 10 views
5

Zastanawiam się nad funkcją w Javie, która, mam nadzieję, istnieje. Chcę iterować przez Arraylist (powiedzmy klasy A), która zawiera obiekty klasy B i C, które oba rozszerzają A. Pomysł, chcę tylko iteracji (na przykład) obiektów klasy B w ArrayList.Iterowanie poprzez Arraylist z rozszerzonymi klasami

Jak to jest możliwe, jak na przykład w poniższym kodzie i bez długiego?

Główna klasa:

 import java.util.*; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    Test() { 
     ArrayList<A> a = new ArrayList<A>(); 
     a.add (new B()); 
     a.add (new C()); 
     a.add (new C()); 
     a.add (new B()); 
     a.add (new C()); 
     for (A aObject : a) { // this works, I want it shorter 
      if (aObject instanceof B) { 
       B b = (B) aObject; 
       System.out.println (b.hi); 
      } 
     } 
     for (B b : a) // like this? 
      System.out.println (b.hi); 
    } 
} 

A:

public class A { 

} 

B:

public class B extends A { 
    String hi = "hi"; 
} 

C:

public class C extends A { 

} 

EDIT: Ponieważ tak wiele osób odpowiada na to: Wiem o używaniu instanceof. Chcę szybszą drogę do pętli wszystkich obiektów w tablicy, której klasa jest B.

+0

Musisz powtórzyć całą listę i każdy obiekt na liście, aby sprawdzić, czy należy do klasy, którą chcesz. Możesz zajrzeć do keywork "instancji" jak już wspomniano w odpowiedzi poniżej ... ale obawiam się, że kod będzie podobny do tego, który masz (ale instancja podejścia jest lepsza/czystsza) – Pitelk

+0

The pytanie, zanim edytowałeś, nie było jasne, o co prosiłeś. – JRSofty

Odpowiedz

2

Można zrobić filtr wielokrotnego użytku klasa dla niego, podobna do FileFilter. (Zobacz odpowiedź korifeya na użycie guawy.) Poza tym, nie, nie ma żadnej istniejącej funkcjonalności, aby to zrobić. Dodatkowo, każda istniejąca funkcja musiałaby robić dokładnie to, co robisz, ponieważ typy List nie mają żadnej wiedzy na temat tego, gdzie znajdują się różne klasy obiektów na liście. (Będzie musiał je powtórzyć, aby je znaleźć).

Jeśli potrzebujesz rozwiązania o wysokiej wydajności, możesz rozważyć przechowywanie oddzielnych list dla oddzielnych instancji - w zamian lub w uzupełnieniu do aktualna lista. Można nawet zawinąć to w klasę złożoną, która oferowałaby obie funkcje (wszystkie instancje i instancje według klasy) za pośrednictwem wspólnego API.

+0

Dzięki za odpowiedź, byłem po prostu ciekawy, nie potrzebowałem wysokiej wydajności, ale może kiedyś będę go potrzebować. Świetna odpowiedź! – Hidde

2

Można użyć guava

tak:

for (B b: Iterables.filter(a, B.class)) { 
System.out.println (b.hi); 
} 
+0

To nie robi tego samego co OP: filtr akceptuje instancje C, podczas gdy OP przyjmuje tylko instancje B, które nie są C. OP może jednak użyć predykatu wielokrotnego użytku. –

+0

C rozszerza A, nie B. Dlaczego filtr akceptuje C? – korifey

+0

Przepraszam, mój błąd. Gdyby C był rozszerzony B, a gdyby OP zachował swój pierwotny kod, w którym porównałby klasy zamiast używania instanceof, wówczas istniałaby różnica. –

0

Zgadzam się z JRSofty.

for (A aObject : a) { 
    if (aObject instanceof B) { // <-- This is as short I can make it 
     B b = (B) aObject; 
     System.out.println (b.hi); 
    } 
} 
+0

Pokazałem już ten przykład, bez wystąpieniaof, ale to samo. – Hidde

0

Można napisać prostszą pętlę tak:

for (A aObject : a) 
    if (aObject instanceof B) 
     System.out.println(((B) aObject).hi); 

Jest to lepszy pomysł, za pomocą operatora instanceof. Ale w celu odfiltrowania instancji listy, które nie są typu B, należy zintegrować dodatkową bibliotekę kolekcji, ponieważ ta operacja nie jest obsługiwana bezpośrednio przez standardowy interfejs API kolekcji. Może Guava lub LambdaJ mają wsparcie dla rodzaju operacji filtrowania, którą chcesz zrobić, jeszcze nie sprawdziłem.