2010-09-15 4 views
4

J'ai un List d'objets. Je veux parcourir cette liste d'objets et traiter certains sous-ensembles d'objets en fonction d'une condition et finalement créer une nouvelle liste d'objets avec certains objets traités étant éliminés.Itération et traitement d'une ArrayList

Quelle est la meilleure façon de faire cela?

Exemple:

objet réel: List<Cars>

  1. Itérer cette liste et trouver Cars avec la même vitesse.
  2. Dans cet ensemble plus petit de Cars, ceux qui sont du même modèle doivent être éliminés.
  3. Enfin, après l'élimination, je reçois la nouvelle liste.
+0

Ainsi peut le même modèle ont deux vitesses différentes? – Carlos

+1

Pouvez-vous donner un exemple concret dans votre exemple? Comment cela serait-il filtré: ** Civic 50 | Civic 75 | Camry 50 | Civic 50 | Camry 75 ** –

Répondre

7

Google Guava libraries ont:

Iterables.filter(cars, new Predicate<Car>() { 
    @Override 
    public boolean apply(Car car) { 
     //return true or false depending on whether you 
     // want this car to remain in the list 
    } 
} 

Vous pouvez également utiliser un Set intermédiaire - à savoir

cars = new ArrayList<Car>(new HashSet<Car>(cars)); 

où vous avez correctement mis en œuvre hashCode et equals. Cette option est viable si c'est l'identité de votre voiture.


Vous pouvez également utiliser un itérateur:

for (Iterator<Car> it = cars.iterator(); it.hasNext();) { 
    Car car = it.next(); 
    if (conditions here) { 
     it.remove(); 
    } 
} 

D'ailleurs, je suis conscient que les exemples ci-dessus ne résolvent pas le problème complètement - vous devriez toujours considérer ce itérer dans le boucles externes.

+0

Je vous recommande de faire référence à Goyava plutôt qu'à google-collections. C'est fondamentalement juste obsolète maintenant. – ColinD

+0

J'allais aussi le remettre en question, mais je ne pense pas que cela ait vraiment un rapport avec ce que les PO essayent de faire, si vous lisez attentivement. Vos première et troisième suggestions sont applicables pour une décision de filtrage qui peut être appliquée sur chaque élément indépendamment des autres éléments; l'exemple de l'OP ne correspond pas à cela. La deuxième suggestion repose sur une condition qui n'est probablement pas vraie. –

+0

bien, une autre itération dans le prédicat/itération externe, s'il doit comparer aux autres membres de la liste devrait faire. O (n^2), mais .. – Bozho

3

Si vous cherchez à faire des comparaisons personnalisées, alors vous devez définir un Comparator<Car> et ensuite simplement faire une boucle dans les voitures.

List<Car> originalList; 
Comparator<Car> c = new CarSpeedComparator(); 
List<Car> result = carFilter(originalList, c); 

/// Below is the filter method 

public static List<Car> carFilter(List<Car> original, Comparator<Car> comp) 
    List<Car> result = new ArrayList<Car>(); 
    // Process each car 
    for (Car car: original) { 
     boolean containsC = false; 
     // now we check each car in the result 
     // to see if we already have an equivalent car 
     for (int i = 0; i < result.size(); i++) { 
      // if the two cars are equivalent under the rules 
      // then we already have that car in the list 
      if (comp.compare(result.get(i), car) == 0) { 
       containsC = true; 
       break; 
      } 
     } 
     // if the result does not contain an equivalent car, 
     // add it to the list 
     if (!containsC) result.add(car) 
    } 
    return result; 
} 

//// Implementation of one of the necessary comparators 

public class CarSpeedComparator implements Comparator<Car> { 
    public int compare(Car c1, Car c2) { 
     return c1.getSpeed() - c2.getSpeed(); 
    } 
} 

La liste résultante ne contiendra qu'une voiture de chaque vitesse.

+0

mais mon traitement se produira pour un groupe d'objets – Magggi

+0

@user, donc, vous voulez supprimer toutes les voitures qui ont la même vitesse qu'une autre voiture dans la liste? – jjnguy

+0

@user, voir ma mise à jour – jjnguy

0

Si vous le faisiez à plusieurs reprises sur de grandes listes, vous voudriez être plus efficace. Gardez une liste d'objets, mais gardez également des listes séparées pour chaque modèle de voiture; Hashtable<String, List> models. De cette façon, vous avez déjà fait la partie modèle pour les futures sortes. Il prend un peu plus de mémoire, mais beaucoup moins de temps pour chercher.

1

Il semble que ce que vous pourriez vouloir faire d'abord est d'indexer les voitures dans votre liste par la vitesse. Une fois que vous avez fait cela, il pourrait être plus facile de faire le reste du traitement que vous recherchez.Multimap s de Guava sont bons pour cela:

ImmutableListMultimap<Integer, Car> speedIndex = Multimaps.index(cars, 
    new Function<Car, Integer>() { 
     public Integer apply(Car from) { 
     return from.getSpeed(); 
     } 
    }); 

Maintenant speedIndex sera un multimap qui vous permet de faire quelque chose comme ceci:

for (Integer speed : speedIndex.keySet()) { 
    ImmutableList<Car> carsWithSpeed = speedIndex.get(speed); 
    // Do stuff 
} 

Cela vous donne des regroupements de toutes les voitures dans la liste originale avoir la même vitesse. Vous pourriez alors faire n'importe quel traitement sur eux que vous vouliez. Vous pourriez vouloir indexer ce groupe de voitures par modèle, en vous donnant des groupes de voitures qui ont à la fois la même vitesse et le même modèle. Vous pouvez ensuite retirer ces voitures de la liste d'origine si vous le souhaitez. Alternativement, si vous ne voulez pas du tout modifier la liste d'origine, mais simplement obtenir une copie de la liste avec un ensemble de voitures retirées, vous pouvez ajouter chaque voiture à Set, puis obtenir la copie avec ces voitures retirées comme ceci:

Set<Car> carsToRemove = ...; 
List<Car> filteredList = Lists.newArrayList(Iterables.filter(cars, 
    Predicates.not(Predicates.in(carsToRemove)))); 
0

Pour moi, il semble que l'OP veut juste un ensemble unique de paire (modèle, vitesse). Si oui, voici un moyen facile de le faire:

class Car { 
    private final String model; 
    private final int speed; 

    public int hashCode(){ 
     return model.hashCode() + speed; 
    } 

    public boolean equals(Object obj){ 
     //check on null/different class omitted. 
     Car other = (Car)obj; 
     return this.model.equals(obj.model) && this.speed == other.speed; 
    } 
} 

puis

Set<Car> cars = new HashSet<Car>(originalListOfCars);