Sitemap
Bishal Saha

Bishal Saha

Functional Interface : Consumer

3 min readJul 22, 2026

--

Press enter or click to view image in full size
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

Socket

Imagine it as

Input
↓

Socket
↓

Do something
↓

No return value

Consumer means

“I consume something.”

Like

Eat food

Input = Food

Output = Nothing

Same 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 code

Not 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:

  1. Thread
  2. Lambda Expression
  3. 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);

--

--