Functional Interface : Consumer
public Consumer<Socket> getConsumer() {
return (clientSocket) -> {
try (PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(), true)) {
System.out.println("Server is connected with client" + clientSocket.getRemoteSocketAddress());
toClient.println("Hello from server " + clientSocket.getInetAddress());
} catch (IOException ex) {
ex.printStackTrace();
}
};
}Now look at this code
We have
public Consumer<Socket> getConsumer()Let’s understand only this line.
Consumer is already a Functional Interface provided by Java.
Internally it looks almost like
interface Consumer<T> {
void accept(T t);
}Only one method
void accept(T t);That’s why it is a Functional Interface.
What is Consumer<Socket>?
This means
Consumer
takes
SocketImagine it as
Input
↓
Socket
↓
Do something
↓
No return valueConsumer means
“I consume something.”
Like
Eat food
Input = Food
Output = NothingSame idea.
Consumer consumes data.
The lambda function
(acceptedSocket) -> {
try{
...
}
}looks magical. Actually Java converts it into this
new Consumer<Socket>() {
@Override
public void accept(Socket acceptedSocket){
try{
...
}
}
}Exactly the same thing.
Lambda is only shorter syntax.
Let’s compare
Without lambda
public Consumer<Socket> getConsumer() {
return new Consumer<Socket>() {
@Override
public void accept(Socket clientSocket) {
try (PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(), true)) {
System.out.println("Server is connected with port " + clientSocket.getRemoteSocketAddress());
toClient.println("Hello from server " + clientSocket.getInetAddress());
} catch (IOException ex) {
ex.printStackTrace();
}
}
};
}With lambda
public Consumer<Socket> getConsumer() {
return (clientSocket) -> {
try (PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(), true)) {
System.out.println("Server is connected with port " + clientSocket.getRemoteSocketAddress());
toClient.println("Hello from server " + clientSocket.getInetAddress());
} catch (IOException ex) {
ex.printStackTrace();
}
};
}What happens in this method?
public Consumer<Socket> getConsumer() {means
“This method returns a Consumer.”
Not a String.
Get Bishal Saha’s stories in your inbox
Join Medium for free to get updates from this writer.
Not an int.
It returns a piece of behavior.
Think
Method
↓
Returns codeNot data.
Whenever someone calls
getConsumer.accept(clientSocket);run this code.
How use this
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.function.Consumer;
public class Server {
public Consumer<Socket> getConsumer() {
return (clientSocket) -> {
try (PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(), true)) {
System.out.println("Server is connected with port " + clientSocket.getRemoteSocketAddress());
toClient.println("Hello from server " + clientSocket.getInetAddress());
} catch (IOException ex) {
ex.printStackTrace();
}
};
// return new Consumer<Socket>() {
// @Override
// public void accept(Socket clientSocket) {
// try (PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(), true)) {
// System.out.println("Server is connected with port " + clientSocket.getRemoteSocketAddress());
// toClient.println("Hello from server " + clientSocket.getInetAddress());
// } catch (IOException ex) {
// ex.printStackTrace();
// }
// }
// };
}
public static void main(String[] args) {
System.out.println("Starting server...");
Server server = new Server();
int port = 8010;
try(ServerSocket serverSocket = new ServerSocket(port)) {
serverSocket.setSoTimeout(10000);
while(true) {
System.out.println("Server is listening on port " + port + "...");
Socket connectedSocket = serverSocket.accept();
Thread thread = new Thread(() -> server.getConsumer().accept(connectedSocket));
thread.start();
}
}catch(IOException ex) {
ex.printStackTrace();
}
}
}Thread thread = new Thread(() -> server.getConsumer().accept(connectedSocket));This single line combines three Java concepts:
- Thread
- Lambda Expression
- Functional Interface (
Consumer)
Let’s break it down piece by piece.
Start from the inside
The innermost part is:
server.getConsumer()This method returns a Consumer<Socket> object.
Think of it like this:
Server
│
│ getConsumer()
▼
Consumer<Socket>Nothing executes yet.
You’re simply getting an object whose job is to process a socket.
.accept(connectedSocket)?
Java executes the lambda inside getConsumer().
It’s equivalent to:
Consumer<Socket> consumer = server.getConsumer();
consumer.accept(connectedSocket);Now look at the Thread
The constructor expects a Runnable.
Internally it looks like
public Thread(Runnable target)And Runnable is a Functional Interface.
interface Runnable {
void run();
}Since it has only one abstract method, we can use a lambda.
Now combine everything
This
Thread thread = new Thread(
() -> server.getConsumer().accept(connectedSocket)
);becomes
Runnable runnable = new Runnable() {
@Override
public void run() {
server.getConsumer().accept(connectedSocket);
}
};
Thread thread = new Thread(runnable);








