0

How would I turn a for loop into java8 style, but still keeping track of the index and instantiate new objects in the loop?

For example, I currently have a block that pretty much looks for [approve, disapprove..] pattern and filters out the approved one while modifying the disapproved entry. My logic is to check by index. Code is below:

List<Obj> ret = new ArrayList<>(); 
for (int i = 0; i < res.size() - 1; i++) {
     Obj curr = res.get(i);
     Obj next = res.get(i + 1);

     if (curr.getStatus().equals(APPROVED.toString()) &&
         next.getStatus().equals(DISAPPROVED.toString()) {
         next.setRate(null);
         next.setRateDate(curr.getRateDate());
     }
     ret.add(curr);
}

How can I turn this into java8 style with say .map() or .filter()?

Thanksss!

EDIT: no more deletion while iterating

bZhang
  • 307
  • 1
  • 2
  • 12

2 Answers2

2

This is the best way you can do this.

Reason: You can create a stream of res but you are changing value based on adjacent element and accessing adjacent element in streams wouldn't result in a simple solution.

An Abstract from an accurate reason:

The Java 8 streams library is primarily geared toward splitting streams into smaller chunks for parallel processing, so stateful pipeline stages are quite limited, and doing things like getting the index of the current stream element and accessing adjacent stream elements are not supported.

A typical way to solve these problems, with some limitations, of course, is to drive the stream by indexes.

Community
  • 1
  • 1
Pankaj Singhal
  • 15,283
  • 9
  • 47
  • 86
1

While I certainly agree with the other answer, part of the answer also suggests:

A typical way to solve these problems, with some limitations, of course, is to drive the stream by indexes.

Thus, one can go about it this way:

List<Obj> accumulator = new ArrayList<>();
IntStream.range(0, res.size() - 1)
         .mapToObj(i -> new AbstractMap.SimpleEntry<>(res.get(i), res.get(i + 1)))
         .filter(entry -> entry.getKey()
                               .getStatus().equals(APPROVED.toString()) &&
                         entry.getValue()
                             .getStatus().equals(DISAPPROVED.toString())
         .forEachOrdered(entry -> {
                entry.getValue().setRate(null);
                entry.getValue().setRateDate(entry.getKey().getRateDate());
                accumulator.add(entry.getKey());
         });

This is certainly not as readable as your current approach but it's another way to go about it using the Java-8 stream API.

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126