2011-12-08 24 views
5

Mi sono chiesto una funzione in Java, che spero esista. Voglio scorrere un Arraylist (diciamo della classe A), che contiene oggetti di classe B e C che estendono entrambi A. L'idea, io voglio solo scorrere attraverso (per esempio) gli oggetti della classe B nella ArrayList.Iterating through Arraylist con classi estese

Com'è possibile, come il breve esempio nel codice sottostante e senza quello lungo?

La classe principale:

 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: Perché così tante persone rispondono a questo: io conosco l'uso di instanceof. Voglio un modo più veloce per scorrere tutti gli oggetti nella matrice, di cui la classe è B.

+0

È necessario ripetere l'elenco e per ogni oggetto dell'elenco per verificare se è della classe desiderata. Potresti voler dare un'occhiata all'istanza "istanza di" come già detto in una risposta sotto ... ma temo che il codice sia simile a quello che hai (ma l'istanza di approccio è migliore/più pulita) – Pitelk

+0

la domanda prima della modifica non era chiara su ciò che stavi chiedendo. – JRSofty

risposta

2

si potrebbe fare un filtro riutilizzabile classe per esso, simile a FileFilter. (Vedi la risposta di korifey per l'uso di guava.) Oltre a questo, no, non esiste alcuna funzionalità esistente per farlo. Inoltre, qualsiasi funzionalità esistente dovrebbe fare esattamente ciò che si sta facendo in ogni caso, poiché i tipi List non hanno alcun modo di sapere dove si trovano le diverse classi di oggetti nell'elenco. (Dovrebbe scorrere anche su di loro per trovarli.)

Se si necessita di una soluzione ad alte prestazioni intorno a questo, si potrebbe considerare la memorizzazione di elenchi separati per le istanze separate - in sostituzione o in aggiunta al proprio lista corrente. Si potrebbe anche concludere questo in una classe composita che offrirebbe entrambe le funzionalità (tutte le istanze e le istanze per classe) tramite un'API comune.

+0

Grazie per la risposta, ero solo curioso, non c'è bisogno di prestazioni elevate, ma forse ne avrò bisogno una volta. Bella risposta! – Hidde

2

È possibile utilizzare guava

Ti piace questa:

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

Questo non fa la stessa cosa dell'OP: il filtro accetta istanze C, mentre l'OP accetta solo istanze B che non sono C. L'OP potrebbe tuttavia utilizzare un predicato riutilizzabile. –

+0

C estende A, non B. Perché il filtro accetta C? – korifey

+0

Mi dispiace, mio ​​errore. Se C estendeva B, e se l'OP avesse mantenuto il suo codice originale dove confrontava le classi piuttosto che usando instanceof, allora ci sarebbe stata una differenza. –

0

Concordo con 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

Ho già mostrato questo esempio, senza l'instanceof, ma la stessa cosa. – Hidde

0

È possibile scrivere un ciclo semplice come questo:

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

E 'un'idea migliore utilizzando l'operatore instanceof. Tuttavia, per filtrare le istanze della lista che non sono di tipo B, è necessario integrare una libreria di raccolte aggiuntiva, poiché tale operazione non è supportata direttamente dall'API Collections standard. Forse Guava o LambdaJ hanno il supporto per il tipo di operazione di filtro che si desidera eseguire, non ho ancora controllato.