简体   繁体   中英

Java8 Stream with Multiple List of Objects

I have two List where i want to perform some operations based on the properties of the Object1 and Object2.

Object1:

public class Object1 {
        private String prop1;
        private String prop2;
}

Object2:

public class Object2 {
        private String prop1;
        private String prop2;
        private String prop3;
        private boolean prop4;
}

I want to use streams instead of having big methods around.

Lets say we have the below Lists:

List<Object1> object1List = // List of Object1's
List<Object2> object2List = // List of Object2's

Now, I want to compare prop1 and prop2 from both lists and if they are equal i want to get prop3 from Object2 and based on prop3 now i want to see all elements with prop4 true from Object2 and make sure that all with true .

Example:

Object1:
prop1  |  prop2
test1     value1
test1     value2

Object2:
prop1 | prop2 | prop3 | prop4
test1   value1  some    true
test1   value2  some1   true
test2   value3  some    true

Now from the above example, i want to stream both the list and compare the list and if both the prop1 and prop2 are equal, i want to get prop3 in the case "some" and get all prop4 values "true" with prop3 value "some" and see if prop1 and prop2 are in the first list of Object and collect them in a set. I can do this in traditional way but streams seems more readable with less lines of code. I am just learning streams any ideas are appreciated!

As I was bored enough to figure out what this question was asking, here's an example of implementing this functionality using Streams. The key here is to filter/(any)Match based on a Predicate that applies for every element of a stream.

Main.java

import java.util.*; import java.util.stream.*;
class Main
{
  public static void main(String[] args) 
  {
    List<Object1> l1 = new ArrayList<>();//referred to as "first list" in comments
    List<Object2> l2 = new ArrayList<>();//referred to as "second list" in comments
    l1.add(new Object1("test1","value1"));
    l1.add(new Object1("test1","value2"));
    l2.add(new Object2("test1", "value1", "some", true));
    l2.add(new Object2("test1", "value2", "some1", true));
    l2.add(new Object2("test2", "value3", "some", true));
    //This is the stream of objects2 in second list that matched both prop1 and prop2 for at least one object1 in first list
    Stream<Object2> matchingProp1andProp2 = l2.stream().filter(obj2 -> l1.stream().anyMatch(obj1 -> obj1.prop1().equals(obj2.prop1()) && obj1.prop2().equals(obj2.prop2())));
    matchingProp1andProp2.forEach(match -> {
      //get the ones in second list that have same prop3 as the match and prop4 being true
      Stream<Object2> matchingCriteria = l2.stream().filter(obj2 -> match.prop3().equals(obj2.prop3()) && obj2.prop4());
      System.out.println(matchingCriteria.collect(Collectors.toList()));
    });
  }
}

Option1 - if you think is easier to read each condition separately:

Set<Object2> result = l2.stream().filter(o -> o.getProp3().equals("some"))
                                 .filter(o -> l1.contains(new Object1(o.getProp1(), o.getProp2())))
                                 .filter(Object2::isProp4)
                                 .collect(Collectors.toSet());

Option2 - one filter with all conditions:

result = l2.stream().filter(o -> o.getProp3().equals("some") && l1.contains(new Object1(o.getProp1(), o.getProp2())) && o.isProp4() ).collect(Collectors.toSet());

I've assumed that your Object1 overrides equals and hasCode so you can use contains.

If it is not the case, it's a bit complex as you have to compare prop1 and prop2 separately,instead of objects themself:

result = l2.stream().filter(o -> o.getProp3().equals("some") && o.isProp4())
                    .filter(o1 -> l1.stream().anyMatch(o2 -> o2.getProp1().equals(o1.getProp1()) && o2.getProp2().equals(o1.getProp2())))
                    .collect(Collectors.toSet());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM