- 3,722,780 Users
- 2,244,412 Discussions
- 7,850,084 Comments
Forum Stats
Discussions
Categories
- 16 Data
- 362.2K Big Data Appliance
- 7 Data Science
- 2K Databases
- 599 General Database Discussions
- 3.7K Java and JavaScript in the Database
- 32 Multilingual Engine
- 496 MySQL Community Space
- 7 NoSQL Database
- 7.7K Oracle Database Express Edition (XE)
- 2.8K ORDS, SODA & JSON in the Database
- 420 SQLcl
- 58 SQL Developer Data Modeler
- 185K SQL & PL/SQL
- 21.1K SQL Developer
- 2.4K Development
- 3 Developer Projects
- 32 Programming Languages
- 135.6K Development Tools
- 12 DevOps
- 3K QA/Testing
- 327 Java
- 10 Java Learning Subscription
- 12 Database Connectivity
- 71 Java Community Process
- 2 Java 25
- 11 Java APIs
- 141.2K Java Development Tools
- 8 Java EE (Java Enterprise Edition)
- 153K Java Essentials
- 135 Java 8 Questions
- 86.2K Java Programming
- 270 Java Lambda MOOC
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 14 Java SE
- 13.8K Java Security
- 4 Java User Groups
- 22 JavaScript - Nashorn
- 18 Programs
- 147 LiveLabs
- 34 Workshops
- 9 Software
- 3 Berkeley DB Family
- 3.5K JHeadstart
- 5.7K Other Languages
- 2.3K Chinese
- 4 Deutsche Oracle Community
- 16 Español
- 1.9K Japanese
- 3 Portuguese
Filter list of Objs with internal dependency

Hi all,
I'm trying to solve in an elegant functional way the following:
Starting from a List<MyObj> list where MyObj has as properties id, Status (enum), duration, parentId I'd like to filter this list with only MyObjs with parentId = null (so only fathers) with child (child_parentId = father_id in one-to-one relationship) having status = Completed and duration (long) > 20L.
e.g.
initial list
MyObjFather1: id=f1, Status.Completed, 40L, null
MyObjChild1: id=c1, Status.Completed, 25L, f1
MyObjFather2: id=f2, Status.Completed, 10L, null
MyObjChild2: id=c2, Status.Completed, 10L, f2
return list
MyObjFather1: id=f1, Status.Completed, 40L, null
It's pretty simple in "normal" Java but I'd like to use the functional approach
Any suggestions
Answers
-
You could do something like this:
List<MyObj> initialList; // Your list
Observable<List<MyObj>> finalListObs = Observable.from(initialList)
.filter(element -> {
if(element.getString("parentId") == null)
return true;
else
return false;
})
.filter(element -> {
if(element.getString("status").equals("Completed"))
return true;
else
return false;
})
.filter(element -> {
if(element.getLong("duration") > 20L)
return true;
else
return false;
})
.toList();
finalListObs.subscribe(System.out::print); // This would print the resulting list of element f1
The if-else blocks are just to make code more clear, but you could replace them with a simple: return (expression).
Another way would be as simple as this:
List<JsonObject> newList = new ArrayList<JsonObject>();
initialList.forEach(elem -> {
if(elem.getString("parentId") == null &&
elem.getString("status").equals("Completed") &&
elem.getLong("duration") > 20L)
newList.add(elem);
});
Hope that helps.
Best regards, Lupita.
-
Thanks Lupita for your snippet but it doesn't solve the problem.
I need only the Fathers (objs with parentId = null) only in case their child (objs with parentId = id of the parent) has status = Completed AND duration > 20L
In regular Java I'd split the list in 2 different maps<String, Obj>, FathersMap and ChildsMaps, using the obj.getId as key. Looping the ChildsMap in case the conditions, status = Completed && duration > 20L, are satisfied add into the finalList the element from the FathersMap having the id = child.getParentId
Many thanks
-
Oh I hadn't understand what you meant before...
How about this?
MyObj parent = null;
List<MyObj> initialList; // Your list
List<MyObj> children = new ArrayList<MyObj>();
initialList.forEach(elem -> {
if(elem.getString("parentId") != null)
children.add(elem);
});
Observable<List<MyObj>> finalListObs = Observable.from(initialList)
.filter(element -> element.getString("parentId") == null)
.map(element -> {
parent = null;
children.forEach(child -> {
String child_father = child.getString("parentId");
if(child_father.equals(element.getString("id"))){
if(child.getString("status").equals("Completed")
&& child.getLong("duration") > 20L)
parent = element;
}
});
return parent;
})
.filter(parent -> parent != null)
.toList();
finalListObs.subscribe(System.out::println);
Give it a try, hope it helps.
-
Hi @Guadalupe Estrada Flores, thanks again.
Trying to avoid the foreach as suggest in the MOOC.
What about this solution:
public class Functional {
private static Call callF1 = new Call("idF1", null, Call.Status.Completed, 30L);
private static Call callC1 = new Call("idC1", "idF1", Call.Status.Completed, 20L); //not-valid
private static Call callF2 = new Call("idF2", null, Call.Status.Completed, 35L);
private static Call callC2 = new Call("idC2", "idF2", Call.Status.Completed, 25L); //valid
private static Call callF3 = new Call("idF3", null, Call.Status.Completed, 25L);
private static Call callC3 = new Call("idC3", "idF3", Call.Status.Completed, 15L); //not-valid
private static Call callF4 = new Call("idF4", null, Call.Status.Completed, 50L);
private static Call callC4 = new Call("idC4", "idF4", Call.Status.Completed, 40L); //valid
private static Call callF5 = new Call("idF5", null, Call.Status.Completed, 20L);
private static Call callC5 = new Call("idC5", "idF5", Call.Status.Completed, 10L); //not-valid
private static Call callF6 = new Call("idF6", null, Call.Status.Completed, 60L);
private static Call callC6 = new Call("idC6", "idF6", Call.Status.NotCompleted, 50L); //not-valid
public static void main(String... args) {
List<Call> initialList = Arrays.asList(callC1, callC2, callC3, callC4, callC5, callC6, callF1, callF2, callF3, callF4, callF5, callF6);
Predicate<Call> validChildPredicate = call -> call.getParentId() != null && call.getStatus().equals(Call.Status.Completed) && call.getDuration() > 20L;
List<String> fathersId = initialList.stream().filter(validChildPredicate).map(Call::getParentId).peek(System.out::println).collect(Collectors.toList());
Predicate<Call> validFatherPredicate = call -> call.getParentId() == null && call.getStatus().equals(Call.Status.Completed);
List<Call> finalList = initialList.stream()
.filter(father -> fathersId.stream().anyMatch(id -> id.equals(father.getsId())))
.filter(validFatherPredicate)
.peek(System.out::println)
.collect(Collectors.toList());
}
}
class Call {
public Call(String sId, String parentId, Status status, Long duration) {
this.sId = sId;
this.parentId = parentId;
this.status = status;
this.duration = duration;
}
enum Status {
Completed,
NotCompleted
}private String sId;
private String parentId;
private Status status;
private Long duration;
//getters/setters
@Override
public String toString() {return "Call{" +
"sId='" + sId + '\'' +
", parentId='" + parentId + '\'' +
", status=" + status +
", duration=" + duration +
'}';
}
}
Result:
idF2
idF4
Call{sId='idF2', parentId='null', status=Completed, duration=35}
Call{sId='idF4', parentId='null', status=Completed, duration=50}