2017-09-27 5 views
3

J'ai deux listesEn utilisant java Lambda à se joindre à deux listes sur un attribut commun et de recueillir un autre attribut

List<SampleClassOne> listOne; 
List<SampleClassTwo> listTwo; 

public class SampleClassOne{ 
    private String myProperty; 
    private String myOtherProperty 
    //ommiting getters-setters 
} 

public class SampleClassTwo{ 
    private String myProperty; 
    private String someOtherProperty 
    //ommiting getters-setters 
} 

Je veux faire ce

List<String> someOtherPropertyList; 

for(SampleClassOne One : listOne) { 
    for(SampleClassTwo two : listTwo) { 
     if (one.getMyProperty().equals(two.getMyProperty())){ 
      someOtherPropertyList.add(two.getSomeOtherProperty());    
     } 
    } 
} 

return someOtherPropertyList; 

Puis-je faire tout après le « je veux faire ceci "utilisant Lambdas d'une manière efficace?

Répondre

-1

En utilisant lambdas vous pouvez transformer le code comme:

List<String> someOtherPropertyList; 

listOne.forEach(one -> listTwo.stream().filter(two -> one.getMyOtherProperty().equals(two.getMyProperty())) 
       .map(SampleClassTwo::getSomeOtherProperty).forEach(someOtherPropertyList::add)); 

return someOtherPropertyList; 
+0

ne m'a pas ... :) – shmosel

+0

J'espère que le downvoter laisse une note d'amélioration. Au moins apprendre de quelque chose si tu dois me le dire. – nullpointer

+1

Quand je répondre à une question que j'essaie d'éviter downvoting d'autres réponses que je, autrement, pourraient (à moins qu'ils ne manifestement erronées ou nuisibles), précisément pour éviter une telle irrégularité ou l'apparence de celui-ci. – shmosel

1

Pas particulièrement efficace, mais vous pouvez utiliser les flux pour une approche plus déclarative:

List<String> someOtherPropertyList = listTwo.stream() 
     .filter(two -> listOne.stream() 
       .map(SampleClassOne::getMyProperty) 
       .anyMatch(two.getMyProperty()::equals)) 
     .map(SampleClassTwo::getSomeOtherProperty) 
     .collect(Collectors.toList()); 
+1

maintenant nous avons un foreach vs recueillir :) – nullpointer

1

quelque chose comme ça (je l'espère, je l'ai fait ne pas manquer aucune parenthèse car je n'ai pas compilé ceci)

listTwo.stream() 
     .filter(left -> listOne.stream() 
      .anyMatch(right -> left.getMyProperty().equals(right.getMyProperty()))) 
     .map(SampleClassTwo::getSomeOtherProperty) 
     .collect(Collectors.toList()); 
+0

Le nombre de parenthèses est exact. ;-) –

+0

@MCEmperor thx cool :) – Eugene

0

En écrasant le h fonction de cendres pour retourner le hachage de myProperty, vous pouvez faire ce qui suit. (Peut-être slidley plus efficace des listes itérer alors.)

new HashSet<>(listOne).addAll(listTwo) 
         .stream() 
         .forEach(someOtherPropertyList.add(someOtherProperty)); 
return someOtherPropertyList; 
+0

Tout d'abord, vous ne pouvez pas utiliser 'nouveau HashSet <> (LISTONE) .addAll (listTwo)' vous obtiendrez erreur de compilation, les types génériques de LISTONE et listTwo sont incompatibles. En second lieu, la méthode '' retourne addAll' boolean' –

3

Je recommande penser à performances et écrire comme suit:

Collection<String> myPropertiesFromListOne = listOne.stream() 
      .map(SampleClassOne::getMyProperty) 
      .collect(Collectors.toSet()); // removes duplicated elements 

List<String> someOtherPropertyList = listTwo.stream() 
      .filter(sampleClassTwo -> 
       myPropertiesFromListOne.contains(sampleClassTwo.getMyProperty()) 
      ) 
      .map(SampleClassTwo::getSomeOtherProperty) 
      .collect(Collectors.toList()); 
+1

Ne pas avoir peur d'utiliser des noms de variables plus courtes, de sorte que le prédicat peut entrer dans une ligne ;-) Merci pour – Holger

+1

commentaire @Holger, vous avez raison, Le seul code pour la démo Si vous voulez voir comment j'écris le code, voir ** Exemple du monde réel ** dans la documentation de mon API [http-request] (https://github.com/jsunsoftware/http-request/). –