I guess I misunderstood your question. I thought you had a question
about a JavaFX API in JDK 8. This isn't the place to discuss other Java
APIs.
-- Kevin
Fabrizio Giudici wrote:
Hello.
My question is for the sake of curiosity, not being related to a real
problem - or, better, the problem - which is tiny - can be fixed with
a simple work around. But I'd like to blog a short post about it and
I'd like to check I have all the context. It stemmed from a class
about Java 8 that I recently taught and one of the participants asked
about that.
Everything starts from this code chunk that doensnt' compile:
1.
Stream s = IntStream.rangeClosed(1, 10) // just as an
example to quickly create a Stream
.mapToObj(n -> "String #" + n);
Files.write(Paths.get("/tmp/pippo.txt"), s);
error: no suitable method found for write(Path,Stream)
Files.write(Paths.get("/tmp/pippo.txt"), s);
method Files.write(Path,byte[],OpenOption...) is not applicable
(argument mismatch; Stream cannot be converted to byte[])
method Files.write(Path,IterableCharSequence>,Charset,OpenOption...) is not applicable
(argument mismatch; Stream cannot be converted to
Iterable)
method Files.write(Path,IterableCharSequence>,OpenOption...) is not applicable
(argument mismatch; Stream cannot be converted to
Iterable)
2. Variation.
Files.write(Paths.get("/tmp/pippo.txt"), (Iterable)s);
This gives:
Exception in thread "main" java.lang.ClassCastException:
java.util.stream.IntPipeline$4 cannot be cast to java.lang.Iterable
at StreamIteratorExample.main(StreamIteratorExample.java:13)
Ok, so far it's the fact described here
http://stackoverflow.com/questions/20129762/why-does-streamt-not-implement-iterablet
on why Stream doesn't implement Iterable.
Question A: Is the answer "because iterator() is usually supposed to
be callable multiple times, while in a Stream it can't" correct?
3. This is the known trick around the problem:
final Iterable i = s::iterator;
Files.write(Paths.get("/tmp/pippo.txt"), i);
It works and I think I understand why (Iterable has the same
functional descriptor of Supplier, which is s::iterator, so
they are compatible in assignment - right?).
4. But at this point putting it into the same line gives compilation
error:
Files.write(Paths.get("/tmp/pippo.txt"), s::iterator);
error: no suitable method found for write(Path,s::iterator)
Files.write(Paths.get("/tmp/pippo.txt"), s::iterator);
method Files.write(Path,byte[],OpenOption...) is not applicable
(argument mismatch; Array is not a functional interface)
method Files.write(Path,IterableCharSequence>,Charset,OpenOption...) is not applicable
(argument mismatch; bad return type in method reference
Iterator cannot be converted to Iterator)
method Files.write(Path,IterableCharSequence>,OpenOption...) is not applicable
(argument mismatch; bad return type in method reference
Iterator cannot be converted to Iterator)
5. This at last works:
Files.write(Paths.get("/tmp/pippo.txt"),
(Iterable)s::iterator);
Question B: Why doesn't the compiler autonomously infer that
s::iterator is compatible with Iterable and the cast is needed?
At last, question C: Given all those premises, is there a specific
reason for which Files.write() hasn't been overloaded with a version
capable of accepting a Stream? It would have been the perfect
complement of Files.lines()
Thanks.