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());
    }
}