I'm wondering is there a way to rewrite code like this
public static void main(String[] args) {
final List<String> dataCollection = Collections.emptyList();
final Set<String> someValues = new HashSet<>();
final Iterator<String> iterator = dataCollection.iterator();
while (iterator.hasNext()) {
final String dataItem = iterator.next();
// imagine some calculations
String calculatedData = dataItem;
if (!someValues.contains(calculatedData)) {
logger.error("Skipped data {} because of ...#1", dataItem);
iterator.remove();
continue;
}
for (char element : dataItem.toCharArray()) {
// imagine some other calculations
if (element > 100) {
logger.error("Skipped data {} because of ...#2", dataItem);
iterator.remove();
break;
}
}
}
}
with Stream API so that excluded after filters element were logged.
peek() doesn't work in this case, because it either perform action with every element before filter or after it with remaining items.
So far I managed to design it with logging inside lambda, but it seems verbose, awkward and like side effect. We can wrap it inside some method, but it will only hide that code a bit
public static void main(String[] args) {
final List<String> dataCollection = Collections.emptyList();
final Set<String> someValues = new HashSet<>();
final Iterator<String> iterator = dataCollection.iterator();
dataCollection.stream()
.filter(byCondition1(someValues))
.filter(byCondition2())
.collect(Collectors.toList());
}
private static Predicate<String> byCondition1(Set<String> someValues) {
return dataItem -> {
final boolean remain = someValues.contains(dataItem);
if (!remain) {
logger.error("Skipped data {} because of ...#1", dataItem);
}
return remain;
};
}
private static Predicate<String> byCondition2() {
return dataItem -> {
for (char element : dataItem.toCharArray()) {
// imagine some other calculations
if (element > 100) {
logger.error("Skipped data {} because of element {}...#2", dataItem, element);
return false;
}
}
return true;
};
}
I hope that there is a better way.