Channels and Streams essentially do the same thing, but they are different ways of doing it. They are both sources of data.
A stream is a source/sink where you read or write bytes to or from. Channels work a bit differently. Instead of reading directly from a channel, you pass a ByteBuffer to a Channel, and the Channel will either fill or drain the buffer.
I believe channels are a little bit faster than streams when it comes to reading devices or drives and such, because they are designed to read in bulk. There are also some other methods you can find in FileChannel for fast operations on files.
Personally I prefer using streams most of the time, because writing code for them is a lot less awkward than it is for channels.
File mapping is a nice feature provided by FileChannel. It maps a file to memory, so you can directly edit the file as if you were editing an array of bytes.
A pipe is simply a way of transporting data from one part of your program to another part. Pipes can be implemented with channels, streams, etc.
Let's compare a pipe to, say, a socket connection.
A socket represents the connection between two processes. You can put data in on one side, and it will come out the other side. Pipes work exactly the same way, except they represent a connection between two different parts of the same process, not different processes. For instance, you can have one
thread that investigates something, and it will write its findings into one end of a pipe, and another thread will read from the other end of the pipe and process the data.