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.