UnaryOperator Functional Interface Java Examples

In this post we’ll see examples of Java java.util.function.UnaryOperator functional interface.

UnaryOperator functional interface represents an operation on a single operand returning a result of the same type as its operand. UnaryOperator extends java.util.function.Function interface and provides behavior for the case where the operand and result are of the same type. Since it extends Function so inherits all the methods of the Function interface-

  • andThen(Function<? super R, ? extends V> after)- It is a default interface method which takes another Function as argument and returns a composed Function that performs, in sequence, first the operation of the calling Function followed by the after operation.
  • compose(Function<? super V, ? extends T> before)- It is a default method in Function interface which takes another Function as argument and returns a composed Function that performs, in sequence, first the before operation then the operation of the calling Function.
  • R apply(T t)- Here T is the type of the argument passed to the method and it returns a value of type R. This is the abstract method in this functional interface. If you are writing a Lambda expression that takes single argument of one type and returns a value of the same type then that lambda expression can be written as an implementation of UnaryOperator built-in functional interface where lambda expression implements the apply() method.

identity() method is changed to return the UnaryOperator-

  • identity()- It is a static method that returns a UnaryOperator which returns its input argument.

UnaryOperator interface apply() method example

In the example apply method is implemented as a lambda expression that returns the number squared. Both the passed argument and the return value are of type int.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
  public static void main(String[] args) {
    UnaryOperator unaryOperator = (n) -> n*n;
    System.out.println("3 squared is- " + unaryOperator.apply(3));
    System.out.println("9 squared is- " + unaryOperator.apply(9));
  }
}
Output
3 squared is- 9
9 squared is- 81

UnaryOperator functional interface andThen() method example

If you want to get a number squared and then add another integer to it that can be done as a sequence of operation using andThen() method.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
  public static void main(String[] args) {
    UnaryOperator<Integer> unaryOperator1 = (n) -> n*n;
    UnaryOperator<Integer> unaryOperator2 = (n) -> n + 1;
    System.out.println("Result- " + unaryOperator1.andThen(unaryOperator2).apply(3));
    System.out.println("Result- " + unaryOperator1.andThen(unaryOperator2).apply(9));
  }
}
Output
Result- 10
Result- 82

UnaryOperator functional interface compose() method example

compose() method does the reverse of andThen() method so if we take the previous example and add an integer first and then square it then that sequence can be composed using compose() method.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
  public static void main(String[] args) {
    UnaryOperator<Integer> unaryOperator1 = (n) -> n*n;
    UnaryOperator<Integer> unaryOperator2 = (n) -> n + 1;
    System.out.println("Result- " + unaryOperator1.compose(unaryOperator2).apply(3));
    System.out.println("Result- " + unaryOperator1.compose(unaryOperator2).apply(9));
  }
}
Output
Result- 16
Result- 100

That's all for the topic UnaryOperator Functional Interface Java Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

ArrayBlockingQueue in Java With Examples

ArrayBlockingQueue is a bounded blocking queue which internally uses an array to store elements. This queue orders elements FIFO (first-in-first-out). The head of the queue is the element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. Insertion of the new elements happens at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue.

ArrayBlockingQueue in Java is an implementation of BlockingQueue interface and is part of java.util.concurrent package.

Bounded blocking queue

ArrayBlockingQueue in Java is a bounded blocking queue which internally uses a fixed-sized array to hold elements. Once created, capacity of the queue cannot be changed. Attempts to put an element into a full queue will result in the operation blocking; attempts to take an element from an empty queue will similarly block.

ArrayBlockingQueue is thread-safe

Java ArrayBlockingQueue implementation is thread-safe. All queuing methods in the class achieve their effects atomically using ReentrantLock internally.

ArrayBlockingQueue does not allow null

ArrayBlockingQueue in Java does not accept null elements. It throws NullPointerException on attempts to add, put or offer a null.

public class ArrayBQ {
  public static void main(String[] args) {
    BlockingQueue<Integer> bQueue = new ArrayBlockingQueue<Integer>(10);
    try {
      // putting null
      bQueue.put(null);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.Objects.requireNonNull(Objects.java:221)
	at java.base/java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:362)
	at com.knpcode.programs.ArrayBQ.main(ArrayBQ.java:12)

Java ArrayBlockingQueue Constructors

  • ArrayBlockingQueue(int capacity)- Creates an ArrayBlockingQueue with the given (fixed) capacity and default access policy.
  • ArrayBlockingQueue(int capacity, boolean fair)- Creates an ArrayBlockingQueue with the given (fixed) capacity and the specified access policy.
  • ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c)- Creates an ArrayBlockingQueue with the given (fixed) capacity, the specified access policy and initially containing the elements of the given collection, added in traversal order of the collection's iterator.

ArrayBlockingQueue Java example

BlockingQueue implementations are designed to be used primarily for producer-consumer queues so let's see an example of producer-consumer using ArrayBlockingQueue.

We'll create an ArrayBlockingQueue of capacity 1 and use the put and take methods for insertion and retrieval operations respectively. These methods block the current thread indefinitely until the operation can succeed. Since the queue capacity is 1 so the insertion will be blocked until the element in the queue is consumed.

public class ArrayBQ {
  public static void main(String[] args) {
    BlockingQueue<Integer> bQueue = new ArrayBlockingQueue<Integer>(1);
    // Producer 
    new Thread(()->{
      for(int i = 0; i < 5; i++){
        try {
          bQueue.put(i);
          System.out.println("Added to queue-" + i);                
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }).start();
        
    // Consumer
    new Thread(()->{
      for(int i = 0; i < 5; i++){
        try {
          System.out.println("Consumer retrieved- " + bQueue.take());
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }).start();
  }
}
Output
Added to queue-0
Consumer retrieved- 0
Added to queue-1
Consumer retrieved- 1
Added to queue-2
Consumer retrieved- 2
Added to queue-3
Consumer retrieved- 3
Added to queue-4
Consumer retrieved- 4

ArrayBlockingQueue class methods

In BlockingQueue implementation like ArrayBlockingQueue, methods come in four forms, with different ways of handling operations that cannot be satisfied immediately, but may be satisfied at some point in the future: one throws an exception, the second returns a special value (either null or false, depending on the operation), the third blocks the current thread indefinitely until the operation can succeed, and the fourth blocks for only a given maximum time limit before giving up.

Insertion methods
  • add(E e)- Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning true upon success and throwing an IllegalStateException if this queue is full.
  • offer(E e)- Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning true upon success and false if this queue is full.
  • put(E e)- Inserts the specified element at the tail of this queue, waiting for space to become available if the queue is full.
  • offer(E e, long timeout, TimeUnit unit)- Inserts the specified element at the tail of this queue, waiting up to the specified wait time for space to become available if the queue is full.
Removal methods
  • remove()- Retrieves and removes the head of this queue. Throws NoSuchElementException if this queue is empty.
  • poll()- Retrieves and removes the head of this queue, or returns null if this queue is empty.
  • take()- Retrieves and removes the head of this queue, waiting if necessary until an element becomes available.
  • poll(long timeout, TimeUnit unit)- Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an element to become available.
Checking queue
  • element()- Retrieves, but does not remove, the head of this queue. Throws NoSuchElementException if this queue is empty.
  • peek()- Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
List of other important methods
  • clear()- Atomically removes all of the elements from this queue.
  • contains(Object o)- Returns true if this queue contains the specified element.
  • iterator()- Returns an iterator over the elements in this queue in proper sequence.
  • remove(Object o)- Removes a single instance of the specified element from this queue, if it is present. size()- Returns the number of elements in this queue.
  • toArray()- Returns an array containing all of the elements in this queue, in proper sequence.

Important points about ArrayBlockingQueue

  1. ArrayBlockingQueue is a bounded blocking queue.
  2. ArrayBlockingQueue internally uses fixed-sized array to hold elements.
  3. ArrayBlockingQueue in Java orders elements in FIFO (first-in-first-out) order.
  4. In ArrayBlockingQueue insertion of the new elements happens at the tail of the queue, and the retrieval of the elements happens at the head of the queue.
  5. ArrayBlockingQueue does not allow null elements.
  6. ArrayBlockingQueue class supports an optional fairness policy for ordering waiting producer and consumer threads. If fairness is set to true, threads are granted access in FIFO order.
  7. ArrayBlockingQueue is thread-safe. It uses ReentrantLock for guarding all access.

That's all for the topic ArrayBlockingQueue in Java With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like