0

I wrote this:

Arrays
            .stream(docIDs.split(","))
            .parallel()
            .forEachOrdered(i -> {
                        try {
                            System.out.print(
                                    Files.lines(Paths.get(spamDir +"\\cw12-" + i.substring(10,16) + ".txt"))
                                            .filter(j -> j.matches("^(\\d\\d)\\s" + i)) 
                                            .map(line -> line.substring(0, line.indexOf(" "))) 
                                            .findFirst()    
                                            .orElse("-1")
                            );
                        } catch (Exception e1) {
                            System.out.print("-1");
                        }
                    }
            );

I am printing a part of string as you see above.

I need to put ',' comma between every element(number). { I am gonna check whether I am in last element and I am gonna put ',' commas according to that.This why I need to know if I am in last element. }

I thought so much but I couldn't find a way for solution.How can I do that?

Ali
  • 69
  • 1
  • 1
  • 12
  • the *streams API* is part of java *functional programming* feature. The basic concept of functional programming is that there is no relationship between the element operations. So if you need this relationship you should change back to `for` loop with index. – Timothy Truckle Apr 27 '17 at 17:36
  • Try something like. .. `addcomma=false; for(... ) {if addcomma print ","; print ; addcomma=true;} `...pseudocode is the best I can do from my phone. On the first iteration the flag is false so no comma is printed, print the value and change the flag to true, for every other iteration the flag will be true thous print the comma before the value. – Lohmar ASHAR Apr 27 '17 at 17:36
  • I need to do this with lambda – Ali Apr 27 '17 at 17:39

1 Answers1

3

A couple things:

  • parallel and forEachOrdered basically cancel each other out.
  • parallel is rarely a good idea anyway.
  • You cannot detect whether you're in the last element.
  • There's a better solution anyway.

    System.out.println(
        Arrays.stream(docIDs.split(","))
        .parallel() // included because OP included it
        .map(i -> {
            // this is how you should use Files.lines anyway
            try (Stream<String> lines = Files.lines(Paths.get(spamDir +"\\cw12-" + i.substring(10,16) + ".txt"))) {
               return lines
                           .filter(j -> j.matches("^(\\d\\d)\\s" + i)) 
                                        .map(line -> line.substring(0, line.indexOf(" "))) 
                           .findFirst()    
                           .orElse("-1");
            } catch (IOException e1) {
                return "-1";
            }
        })
        .collect(Collectors.joining(",")));
    

...where the meat of the answer to your original question is to use Collectors.joining instead of trying to do a sequential loop in the first place.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • You saying: "parallel and forEachOrdered basically cancel each other out." ,but I need to do it in fastest way and it must be ordered.What do you suggest? – Ali Apr 27 '17 at 17:45
  • @Aliİ. that you do it exactly as I wrote it. Possibly deleting `.parallel()`, though. – Louis Wasserman Apr 27 '17 at 17:46
  • *`parallel` and `forEachOrdered` basically cancel each other out.* Only because there are no operations in between, right? – shmosel Apr 27 '17 at 17:47
  • @shmosel No. They always cancel each other out. You can't have some of an operation be parallel and some be sequential; that's not how streams work. If you want to do some operations in parallel and some sequentially you must explicitly collect to an intermediate collection or the like and break it up into separate stream operations. – Louis Wasserman Apr 27 '17 at 17:48
  • Are you suggesting parallel streams can't preserve encounter order? I don't think that's correct. See also http://stackoverflow.com/a/29713386/1553851 – shmosel Apr 27 '17 at 17:55
  • No, I didn't say that. `forEachOrdered`, on the other hand, finishes its operation for one element completely before operating on the next element, which defeats the point of parallelism. – Louis Wasserman Apr 27 '17 at 17:55
  • Ah. I suppose it might be able to perform intermediate operations in parallel...though based on what I've seen of the implementation of the stream framework, I would be at least somewhat surprised if it did. But certainly the `forEachOrdered` part of the stream operation will not be performed in parallel, even if `.parallel()` is used. – Louis Wasserman Apr 27 '17 at 17:57