-1

I was playing around with Java 8 and I was trying to convert this below code which earlier had for and while loops but unfortunately I could not convert the while to IntStream.

Can someone help me with this. Also if someone can suggest more better and efficient way. Thanks !

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

public class NestedStreams {

    public static void main(String[] args) {

        ArrayList<String> a1 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "01", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a2 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "02", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a3 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "03", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a4 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "04", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a5 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "05", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a6 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "06", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a7 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "06", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a8 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "06", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a9 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "06", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a10 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "06", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a11 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "06", "90", null, "77", "00001", "AB").collect(Collectors.toList());
        ArrayList<String> a12 = (ArrayList<String>) Stream.of("ABC", "CFR", "DDR", "01", "M", null, "001", null, "00",
                null, "00", null, "00", "06", "90", null, "77", "00001", "AB").collect(Collectors.toList());

        ArrayList<ArrayList<String>> someList = new ArrayList<ArrayList<String>>();
        someList.addAll(Arrays.asList(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12));

        NestedStreams ns = new NestedStreams();
        String status = ns.testMethod(someList);
        if (status.equalsIgnoreCase("working")) {
            System.out.println("we can now do the processing");
        } else {
            System.out.println("failure");
        }

    }

    public String testMethod(ArrayList<ArrayList<String>> someList) {
        try {
            IntStream.range(0, someList.size()).forEach(i -> {
                ArrayList<String> someOtherValues = (ArrayList<String>) someList.get(i);
                someOtherValues.replaceAll(t -> Objects.isNull(t) ? "" : t);
                AtomicInteger count = new AtomicInteger(4);
                AtomicInteger counter = new AtomicInteger(5);
                if (!someOtherValues.get(0).toString().equals("")) {
                    // while (count.intValue() < (someOtherValues.size())) { //Line 62
                    IntStream.range(count.intValue(), someOtherValues.size()).forEach(value -> { //Line 63
                        IntStream.range(0, 3).forEach(k -> {
                            String avalue = someOtherValues.get(count.intValue()).toString();//count is getting increased more than the length of arrayList //Line 65
                            System.out.println(avalue);
                            counter.incrementAndGet();
                        });
                        count.set(counter.intValue());
                        counter.incrementAndGet();
                        System.out.println("The variable value :-" + value);
                        System.out.println("The variable counter :-" + counter);
                        System.out.println("The variable count :-" + count);
                    });
                }
            });
            return "working";
        } catch (Exception e) {
            e.printStackTrace();
            return "failed";
        }
    }
}

The only problem with the code is after changing while to IntStream I am not able to check the condition count < someOtherValues.size() due to which line 65 is resulting in error as count is getting increased more than the ArrayList size.

NOTE : The above code results into java.lang.IndexOutOfBoundsException: Index: 20, Size: 19 You can uncomment the while loop at line 62 and comment the IntStream at line 63 for a fully working code.

geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • In while loop you use `someOtherValues.size()` but at line 63 you use `someList.size()`. Why? – Alex May 16 '21 at 06:15
  • That was a typo @Alex. I literally intended to include those list which I get after every iteration of i variable. Thanks for pointing that out – MysteriousCoder May 16 '21 at 06:26
  • So does it work after you fixed it? – Alex May 16 '21 at 06:29
  • No, that is not the fix, that is what it meant to be, I actually had made a typo, when I checked back my code on eclipse it was someOtherValues.size(). It gives error with the currently edited code. – MysteriousCoder May 16 '21 at 06:35

1 Answers1

0

An IntStream just returns a sequential and ordered stream. You cannot expect it to do a entry-check for each iteration like what a while-loop does. If you want to achieve the same results provided by the while loop, include an if statement to check the condition. I ran this on my machine and it provides the same results.

      IntStream.range(count.intValue(), someOtherValues.size()).forEach(value -> { //Line 63

         // If condition here acts as the condition statement in a loop 
         if(count.intValue() < someOtherValues.size()) {
                  IntStream.range(0, 3).forEach(k -> {
                            
                   String avalue = someOtherValues.get(count.intValue()).toString();//count is getting increased more than the length of arrayList //Line 65
                   System.out.println(avalue);
                   counter.incrementAndGet();
                        });
                        count.set(counter.intValue());
                        counter.incrementAndGet();
                        System.out.println("The variable value :-" + value);
                        System.out.println("The variable counter :-" + counter);
                        System.out.println("The variable count :-" + count);
                   }  
            });

Some points to note:

  1. It is unclear what you are trying to achieve by changing while to IntStream. However, I'll leave that to use-case dependencies. Since you had asked for a better way, I'd suggest to stick with the while loop since it does the job in a much simpler way.
  2. IntStream.range(start, end) provides values that are start-inclusive and end-exclusive
  3. I've made changes just to match with the output that the while loop generates. Again, since you haven't mentioned your goal here, the correctness or the intended output should be taken care by you.

Cheers!

ram
  • 437
  • 2
  • 12
  • 1
    `IntStream.range(start, end) Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive)` fix in answer please – Alex May 16 '21 at 08:04
  • Thanks @ram for your answer. My main intention behind converting the `while` to `IntStream` was just to check whether it is possible to write the entire code using java 8 features. If you could see all the `IntStream` used was earlier a simple `for` loop. Adding an if inside a loop just to check condition doesn't make much sense, its better to stick with the `while` as you pointed out on point 1. Also, I have to do a performance check to check whether this is more efficient or the traditional way. – MysteriousCoder May 16 '21 at 13:19