4
votes

Fournisseur valide pour la méthode de collecte du flux

J'essayais juste de créer quelque chose de similaire à Collectors.toList () mais cela ne semble pas fonctionner

import java.util.ArrayList;

public class ShipmentTracingDTO {

boolean destination = false;

public ShipmentTracingDTO(Boolean destination) {
    this.destination = destination;
}

public ShipmentTracingDTO() {
}

public static void main(String[] args) {
    ArrayList<ShipmentTracingDTO> tracings = new ArrayList<>();
    tracings.add(new ShipmentTracingDTO(true));
    tracings.add(new ShipmentTracingDTO(true));
    tracings.add(new ShipmentTracingDTO(false));
    tracings.add(new ShipmentTracingDTO(false));
    ArrayList<ShipmentTracingDTO> newTracings = new ArrayList<>();

// Error coming for ArrayList::new : The constructed object of type ArrayList is 
//incompatible with the descriptor's return type: R

    tracings.stream().collect(ArrayList::new, (left, right) -> left.add(right), (left, right) -> {
        left.addAll(right);
        return left;
    });
}

private boolean getDestination() {

    return destination;
}

} p >

Ma question est si ArrayList :: new ne fonctionne pas ici, qu'est-ce qui fonctionnera. J'ai essayé différentes variantes mais aucune ne semble fonctionner


0 commentaires

3 Réponses :


5
votes

Vous semblez rechercher:

tracings.stream()
        .collect(ArrayList::new, 
                 (left, right) -> left.add(right), 
                 (left, right) -> left.addAll(right)); // notice no 'return'

qui est identique à la représentation lambda:

tracings.stream()
        .collect(ArrayList::new, 
                 ArrayList::add, 
                 ArrayList::addAll);

Raison : le Stream.collect attend un BiConsumer comme argument, qui a une méthode accept avec le type de retour void .


0 commentaires

6
votes

Changez-le simplement comme ceci,

tracings.stream().collect(ArrayList::new, List::add, List::addAll);

Ce dont vous avez besoin est un BiConsumer PAS un BinaryOperator . Ce que vous passez ci-dessus est un BinaryOperator .

Voici un exemple de BinaryOperator.

BinaryOperator<List<Integer>> s = (left, right) -> {
            left.addAll(right);
            return left;
};

En tant que bonne pratique d'ingénierie, préférez toujours les références de méthode aux lambdas. Voici donc la version améliorée utilisant des références de méthode à la place des lambdas.

tracings.stream().collect(ArrayList::new, (left, right) -> left.add(right), (left, right) -> {
    left.addAll(right);
});


5 commentaires

(gauche, droite) -> left.add (droite) peut être remplacé par List :: add et (gauche, droite) -> left.add ( à droite) par List :: addAll .


Oui, mais ce n'est pas directement lié à la question.


Le PO a demandé "ce qui fonctionnera" . Les références de méthode fonctionneront aussi bien que les lambdas. Mais je préférerais montrer les meilleures pratiques avec des explications, pas seulement résoudre le problème de compilation.


@ETO J'ai mis à jour la réponse selon la suggestion.


Et c'est essentiellement ce que fait Collectors.toList () en interne, bien que la spécification laisse la possibilité de le faire différemment (c'est-à-dire de ne pas renvoyer une ArrayList mais une autre List implémentation). Mais lorsque vous utilisez Collectors.toCollection (ArrayList :: new) , vous obtenez exactement cela. La confusion peut provenir de Collector.of (…) dont la fonction de fusion est un opérateur binaire: tracings.stream (). Collect (Collector.of (ArrayList: : new, List :: add, (l, r) -> {l.addAll (r); return l;}) . Cela permet des optimisations potentielles, c'est-à-dire (l, r) -> { if (l.isEmpty ()) return r; l.addAll (r); return l;}



1
votes

J'essayais juste de créer un peu similaire à Collectors.toList () de la mienne mais ça ne semble pas fonctionner

Bien que les autres réponses spécifient ce que vous avez mal fait, il convient de noter que si vous essayez de créer quelque chose de similaire à toList () mais en même temps spécifiez le type de liste renvoyée, alors Je suggère d'utiliser toCollection qui est spécialement conçu à cet effet.

new ArrayList<>(tracings);

bien que ce ne soit pas mieux que:

tracings.stream().collect(Collectors.toCollection(ArrayList::new));

qui est plus court et plus lisible.


0 commentaires