6 votes

Java 8 Regroupement Concurrent de Flux Parallèles

Supposons que j'ai une classe comme

Classe Personne {
  Chaîne de caractères nom;
  Chaîne de caractères uid;
  Chaîne de caractères téléphone;
}

Je cherche à regrouper tous les champs de la classe. Comment puis-je utiliser des flux parallèles en JAVA 8 pour convertir une

Liste en Map>

où la clé de la carte est la valeur de chaque champ de la classe. JAVA 8 l'exemple suivant regroupe par un seul champ, comment puis-je le faire pour tous les champs d'une classe dans une seule Map?

ConcurrentMap> parGenre =
roster
    .parallelStream()
    .collect(
        Collectors.groupingByConcurrent(Personne::getGenre));

4voto

Aomine Points 42709

Vous pouvez soit chaîner vos collecteurs de regroupement, ce qui vous donnerait une map à plusieurs niveaux. Cependant, ce n'est pas idéal si vous voulez regrouper par plus de 2 champs.

La meilleure option serait de remplacer les méthodes equals et hashcode dans votre classe Personne pour définir l'égalité de deux objets donnés qui, dans ce cas, seraient tous les champs mentionnés. Ensuite, vous pouvez regrouper par Personne, c'est-à-dire groupingByConcurrent(Function.identity()), auquel cas vous obtiendrez :

ConcurrentMap> resultSet = ....

Exemple :

class Personne {
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Personne personne = (Personne) o;

        if (nom != null ? !nom.equals(personne.nom) : personne.nom != null) return false;
        if (uid != null ? !uid.equals(personne.uid) : personne.uid != null) return false;
        return telephone != null ? telephone.equals(personne.telephone) : personne.telephone == null;
    }

    @Override
    public int hashCode() {
        int resultat = nom != null ? nom.hashCode() : 0;
        resultat = 31 * resultat + (uid != null ? uid.hashCode() : 0);
        resultat = 31 * resultat + (telephone != null ? telephone.hashCode() : 0);
        return resultat;
    }

    private String nom;
    private String uid; // ceux-ci devraient rester privés, ne pas les exposer
    private String telephone;

    // getters lorsque nécessaire
    // setters lorsque nécessaire
}

puis :

ConcurrentMap> resultSet = liste.parallelStream()
                .collect(Collectors.groupingByConcurrent(Function.identity()));

4voto

Lino Points 13360

Vous pouvez le faire en utilisant la méthode de fabrique statique of de Collector:

Map> groupBy = persons.parallelStream()
    .collect(Collector.of(
        ConcurrentHashMap::new,
        ( map, person ) -> {
            map.computeIfAbsent(person.name, k -> new HashSet<>()).add(person);
            map.computeIfAbsent(person.uid, k -> new HashSet<>()).add(person);
            map.computeIfAbsent(person.phone, k -> new HashSet<>()).add(person);
        },
        ( a, b ) -> {
            b.forEach(( key, set ) -> a.computeIfAbsent(key, k -> new HashSet<>()).addAll(set));
            return a;
        }
    ));

Comme Holger l'a suggéré dans les commentaires, l'approche suivante peut être préférée à celle ci-dessus:

Map> groupBy = persons.parallelStream()
     .collect(HashMap::new, (m, p) -> { 
         m.computeIfAbsent(p.name, k -> new HashSet<>()).add(p); 
         m.computeIfAbsent(p.uid, k -> new HashSet<>()).add(p); 
         m.computeIfAbsent(p.phone, k -> new HashSet<>()).add(p); 
     }, (a, b) -> b.forEach((key, set) -> {
         a.computeIfAbsent(key, k -> new HashSet<>()).addAll(set));
     });

Il utilise la méthode collect surchargée qui agit de manière identique à ma déclaration suggérée ci-dessus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X