2017-08-09 3 views
3

J'ai un cas comme ci-dessous:Comment affecter la méthode Stream à une fonction dans java 8?

RowDataSet rdsHavingMaxNumericValue = dataList.stream() 
        .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
        .max((r1, r2) -> r1.getId().compareTo(r2.getId())) 
        .get(); 

J'ai deux cas où je dois trouver soit min ou max selon le cas? comment puis-je remplacer l'appel max à la troisième ligne par une fonction afin qu'elle utilise directement la méthode .apply() et effectue l'opération?

I'v Collection.max ou Collection min comme ci-dessous assigné avec succès:

BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation = expComponents[0] == 'M' ? Collections::max : Collections::min; 

et je l'utilise comme ci-dessous:

RowDataSet rds = mrOrlrOperation.apply(dataList, <some comparator>); 

Répondre

3

Il serait sans doute plus simple d'utiliser simplement une condition:

Stream<?> stream = dataList.stream() 
          .filter(r -> r.getLong(NUMERIC_VALUE) != null); 
Comparator<RowDataSet> c = Comparator.comparingLong(RowDataSet::getId); 
RowDataSet rdsHavingMaxNumericValue = 
       expComponents[0] == 'M' ? stream.max(c).get() : stream.min(c).get(); 

vous pouvez stocker l'opération min/max dans un Function séparé si vous veulent:

BiFunction<Stream<RowDataSet>, Comparator<RowDataSet>, RowDataSet>> operation = 
      expComponents[0] == 'M' ? (s, c) -> s.max(c).get() : (s, c) -> s.min(c).get(); 

RowDataSet rdsHavingMaxNumericValue = operation.apply(stream, c); 
+0

Ouais, ressemble à l'option, mais je veux éviter la recherche de cas lors de l'exécution – Ajeetkumar

+0

Que voulez-vous dire? – assylias

+0

Je ne veux pas effectuer d'opérations if else. Je l'ai laissé comme une dernière option – Ajeetkumar

5

Le choix d'utiliser min au lieu de max ne diffère pas d'utiliser encore l'opération max, mais avec un ordre inverse, vous pouvez donc utiliser

Initialisation:

Comparator<RowDataSet> c = Comparator.comparingLong(RowDataSet::getId); 
if(expComponents[0] != 'M') c = c.reversed(); 

Le fonctionnement réel

RowDataSet rdsHavingMaxNumericValue = 
    dataList.stream() 
      .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
      .max(c) 
      .get(); 

Rever chanter la commande n'a aucun impact sur les performances. Cela implique simplement appeler r2.getId().compareTo(r1.getId()) au lieu de r1.getId().compareTo(r2.getId()) ...

Une alternative serait

Comparator<RowDataSet> c = Comparator.comparingLong(RowDataSet::getId); 
BinaryOperator<RowDataSet> op = expComponents[0] == 'M'? 
           BinaryOperator.maxBy(c): BinaryOperator.minBy(c); 

RowDataSet rdsHavingMaxNumericValue = 
    dataList.stream() 
      .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
      .reduce(op) 
      .get(); 

Cette anticipe what min and max would do ...


Vous pouvez utiliser les deux variantes pour créer votre BiFunction, par exemple

Variante 1:

Function<Comparator<RowDataSet>, Comparator<RowDataSet>> 
    maxOrMin = expComponents[0] == 'M'? Function.identity(): Comparator::reversed; 

BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation 
    = (dataList, comparator) -> dataList.stream() 
             .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
             .max(maxOrMin.apply(comparator)) 
             .get(); 

Variante 2:

Function<Comparator<RowDataSet>, BinaryOperator<RowDataSet>> 
    maxOrMin = expComponents[0] == 'M'? BinaryOperator::maxBy: BinaryOperator::minBy; 

BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation 
    = (dataList, comparator) -> dataList.stream() 
             .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
             .reduce(maxOrMin.apply(comparator)) 
             .get(); 

Bien sûr, vous pouvez aussi vivre avec une duplication de code

BiFunction<List<RowDataSet>, Comparator<RowDataSet>, RowDataSet> mrOrlrOperation 
    = expComponents[0] == 'M'? 
     (dataList, comparator) -> dataList.stream() 
              .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
              .max(comparator) 
              .get(): 
     (dataList, comparator) -> dataList.stream() 
              .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
              .min(comparator) 
              .get(); 

Dans les deux cas, la condition expComponents[0] == 'M' est vérifié une seule fois lorsque le BiFunction est créé et jamais évalué lorsque mrOrlrOperation.apply(…) est invoqué.

0

max est une opération de réduction, vous pouvez utiliser le générique reduce:

public void reducing(BiOperator<...> myFunction) { 
    RowDataSet rdsHavingMaxNumericValue = dataList.stream() 
       .filter(r -> r.getLong(NUMERIC_VALUE) != null) 
       .reduce((r1, r2) -> myFunction.apply(r1,r2)) 
       .get(); 
} 
... 
reducing(Integer::max); 
... 
+0

Salut, je trouve ta réponse intéressante mais j'ai du mal à la comprendre pleinement. Les paramètres de BiFunction sont Integer, Integer, Integer? En cas d'Integer :: max, avez-vous manqué l'appel myFunction.apply? – Ajeetkumar

+0

Oui, je l'ai écrit un peu plus vite, en corrigeant ... –

+0

BiFonction ou BiOperator doit être tapé comme vous voulez ... –