There is no need to complicate things too much. Just double get the stream from the list:
int totalSum = obj.stream().mapToInt(i -> i).sum(); int first20 = obj.stream().limit(20).mapToInt(i -> i).sum();
Yes, he will do two passes in the list (and for the second time only for the first 20 elements, so this is not a big deal), so I expect that this is what they want from you to do. It is simple, effective and readable.
To do this in one go, you can use a collector. For example, you can do this as follows:
Map<Boolean, Integer> map = IntStream.range(0, obj.size()) .boxed() .collect(partitioningBy(i -> i < 20, mapping(i -> obj.get(i), summingInt(i -> i)))); int first20 = map.get(true); int totalSum = map.get(true) + map.get(false);
Basically, you index indexes first. Then for each index; you divide them on the map in two lists, one for the first 20 indices and the rest in another list; as a result, we get a Map<Boolean, List<Integer>> .
Then each index is mapped to its value in the original List (with the mapping collector).
Finally, you convert each List<Integer> by summing their values โโinto a single Integer . Then you just get the total amount.
Another workaround with a custom collector:
public static Collector<Integer, Integer[], Integer[]> limitSum(int limit, List<Integer> list) { return Collector.of(() -> new Integer[]{0, 0}, (a, t) -> { a[0] += list.get(t); if(t < limit) a[1] += list.get(t); }, (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, a -> a); }
and usage example:
List<Integer> obj = Stream.iterate(0, x -> x + 1).limit(5).collect(toList());
<h / "> As you can see, this is not very readable and, as mentioned in the comments, it may be appropriate for the loop in this case (although you were asked to use Streams).