I am trying to change the set of code for normal forEach
loops to stream and filters. But finding errors in the way it's getting implemented.
Current Code:
List<Long> validFromPersonIds;
List<Person> existingPersonIds;
Person class has two variables:
Long fromPersonId
Long toPersonId;
List<Long> insertionAvailableValidFromPersonIds = new ArrayList<>(validFromPersonIds);
validFromPersonIds.forEach(fromPersonId -> {
existingPersonIds.forEach(existingPersonId -> {
if(existingPersonId.getToPersonId() == toPersonId && existingPersonId.getFromPersonId() == fromPersonId)
{
insertionAvailableValidFromPersonIds.remove(fromPersonId);
}
});
});
In above code I have validFromPersonIds
and existingPersonIds
list. If any fromPersonId
is existing in the table, I dont want to insert to the table. So, i am trying to remove fromPersonId
if its already existing in the table.
This is working properly.
Using Streams and Filters, tried code:
List<Long> insertionAvailableValidFromPersonIds = new ArrayList<>();
insertionAvailableValidFromPersonIds = validFromPersonIds.stream()
.filter(fromPersonId -> existingPersonIds.stream()
.filter(existingPersonId-> existingPersonId.getToPersonId() == toPersonId && existingPersonId.getFromPersonId() == fromPersonId)
.collect(Collectors.toList()).contains(fromPersonId).collect(Collectors.toList());
But instead of using normal forEach i am trying to use streams and filters, where I get filtered record and collect it as list. But I am not able to come up with correct syntax for that. Could anyone check where I am going wrong here.
looks like you are filtering by fromPersonId
twice.. the first time in the inner filter and then again via this contains. Instead, you can use noneMatch
:
private List<Long> newFilter(List<Long> validFromPersonIds, List<Person> existingPersonIds, long toPersonId) {
return List<Long> filtered = validFromPersonIds.stream()
.filter(fromPersonId -> existingPersonIds.stream()
.noneMatch(eid -> eid.getToPersonId() == toPersonId && eid.getFromPersonId() == fromPersonId)
)
.toList();
}
Updated the answer with a test:
@Test
public void test() {
List<Long> validFromPersonIds = List.of(1l, 2l, 3l, 4l);
List<Person> existingPersonIds = List.of(
new Person(1l, 2l)
);
long toPersonId = 2l;
assertThat(newFilter(validFromPersonIds, existingPersonIds, toPersonId))
.containsExactlyElementsOf(currentFilter(validFromPersonIds, existingPersonIds, toPersonId));
}
// current behavior described in the question
private List<Long> currentFilter(List<Long> validFromPersonIds, List<Person> existingPersonIds, long toPersonId) {
List<Long> insertionAvailableValidFromPersonIds = new ArrayList<>(validFromPersonIds);
validFromPersonIds.forEach(fromPersonId -> {
existingPersonIds.forEach(existingPersonId -> {
if (existingPersonId.getToPersonId() == toPersonId
&& existingPersonId.getFromPersonId() == fromPersonId) {
insertionAvailableValidFromPersonIds.remove(fromPersonId);
}
});
});
return insertionAvailableValidFromPersonIds;
}