My first attempt at using a stream and a lambda expression:
Stream<TableType> myTTStream = Arrays.stream( T[source] ); // T[source] is a 1D row from a 2D array
Optional<TableType> closest = myTTStream
.filter( tt -> !tt.visited ) // tt is each TableType object in the stream; select for unvisited
.sorted( (tt1, tt2) -> Integer.compare(tt1.dist, tt2.dist) ) // sort them by distance to an output stream
.findFirst() // get the first (lowest) distance (returns a possibly empty Optional describing the first element)
;
return ( !closest.isPresent() || closest.get().dist == Integer.MAX_VALUE ) ? -1 : closest.get().dist; // have to get the value from the Optional
The code creates a stream from a row of the T[][] array, filters it for the boolean visited false, sorts the result, and returns the first (lowest-valued) item of the stream. It seems to work except when no items get through the filter, in which case findFirst() causes an error leading ultimately to a null pointer exception.
I don't understand this because findFirst() returns an Optional, which according to the docs, may be empty. So what's the problem? If it's due to the sorted() method being fed an empty stream, then why doesn't that line cause the error?
I'm pretty sure there are no null elements in the T array.
The stack trace (the code above is the body of the method "closestUnvisited"; line 238 is the ".findFirst()" call):
Exception in thread "main" java.lang.NullPointerException
at GraphM.lambda$0(GraphM.java:236)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174)
at java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
at GraphM.closestUnvisited(GraphM.java:238)
at GraphM.findShortestPath(GraphM.java:167)
at GraphM.main(GraphM.java:343)