How about using a map to hold the index and then good 'ol for loop:
List<Pair<SomeObject, Integer>> process(List<SomeObject> input) {
List<Pair<SomeObject, Integer>> result = new ArrayList<>();
Map<Integer, Pair<SomeObject, Integer>> map = new HashMap();
List<SomeObject> couldBeProcessed = new ArrayList<>();
for (int i = 0; i < input.size(); i++) {
if (couldBeProcessed(input.get(i))) {
couldBeProcessed.add(obj);
} else {
map.put(i, Pair.newInstance(obj, 0));
}
}
List<Pair<SomeObject, Integer>> processResult = processInBatch(couldBeProcessed);
for (int i = 0; i < input.size(); i++) {
if (map.containsKey(i)) {
result.add(map.get(i));
} else {
result.add(processResult.remove(0));
}
}
}
You can also use Map#computeIfAbsent
to make the second loop more compact:
for (int i = 0; i < input.size(); i++) {
result.add(map.computeIfAbsent(i, index -> processResult.remove(0));
}
P.S.: The elements of processResult
must have the same indices as respective objects from the original list.
@Misha suggests a more natural way to handle the processed queue - by using Deque
:
Deque<Pair<SomeObject, Integer>> processResult = new ArrayDeque(processInBatch(couldBeProcessed));
for (int i = 0; i < input.size(); i++) {
if (map.containsKey(i)) {
result.add(map.get(i));
} else {
result.add(processResult.removeFirst());
}
}