November 26, 2021

Java HashMap compute() With Examples

The Java HashMap compute() method is used to compute a new value for the specified key.

Syntax of compute() method

compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

The parameters are-

  1. key- Key with which the computed value has to be mapped.
  2. remappingFunction- It is an expression of type BiFunction functional interface used to compute a value.

Method returns a new value associated with the specified key or null if there is no new values. If the remapping function returns null, the mapping is removed (or remains absent if initially absent).

compute() method Java examples

1. In this example a new value is computed for the specified key. For the example a HashMap is created with product name as key and price as value. Then compute() is used to change the price (value) for the specified key.

import java.util.HashMap;
import java.util.Map;

public class MapComputeDemo {
  public static void main(String[] args) {
    Map<String, Double> products = new HashMap<>();
    products.put("Laptop", 1200.0);
    products.put("RAM", 60.50);
    products.put("USB", 10.45);
    products.put("Mouse", 15.0);
    System.out.println("*** Initial Values ***");
    System.out.println(products);
    // Laptop at 20% discount
    products.compute("Laptop", (k, v)-> v- (v*20/100));
    System.out.println("*** After Compute ***");
    System.out.println(products);
    
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=15.0, USB=10.45, RAM=60.5}
*** After Compute ***
{Laptop=960.0, Mouse=15.0, USB=10.45, RAM=60.5}

2. In this example we’ll see what happens if the remappingFunction returns null. In that case the (key, value) pair should be removed. To verify that the function explicitly returns null in the code.

public class MapComputeDemo {
  public static void main(String[] args) {
    Map<String, Double> products = new HashMap<>();
    products.put("Laptop", 1200.0);
    products.put("RAM", 60.50);
    products.put("USB", 10.45);
    products.put("Mouse", 15.0);
    System.out.println("*** Initial Values ***");
    System.out.println(products);
    // remappingFunction returns null
    products.compute("Laptop", (k, v)-> null);
    System.out.println("*** After Compute ***");
    System.out.println(products);
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=15.0, USB=10.45, RAM=60.5}
*** After Compute ***
{Mouse=15.0, USB=10.45, RAM=60.5}

As you can see the product “Laptop” is removed.

3. Using compute() method to compute all values in the HashMap. In the products HashMap if you want to increase price by 10% for all the products.

public class MapComputeDemo {
  public static void main(String[] args) {
    Map<String, Double> products = new HashMap<>();
    products.put("Laptop", 1200.0);
    products.put("RAM", 60.50);
    products.put("USB", 10.45);
    products.put("Mouse", 15.0);
    System.out.println("*** Initial Values ***");
    System.out.println(products);
    products.forEach((k,v) -> products.compute(k, (key, value)-> value + (value*10/100)));
    System.out.println("*** After Compute ***");
    System.out.println(products);
    
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=15.0, USB=10.45, RAM=60.5}
*** After Compute ***
{Laptop=1320.0, Mouse=16.5, USB=11.495, RAM=66.55}

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


You may also like

November 23, 2021

Map#putIfAbsent() in Java With Examples

In this tutorial you will see how to use putIfAbsent() method in Java HashMap. The putIfAbsent() method inserts the specified value if the passed key is not already present in the HashMap or the key is null. Using this method gives you an option to check if key is already present or not, before associating a value with the key. What this method does in a single statement can be explained as-

 V v = map.get(key);
 if (v == null)
     v = map.put(key, value);

 return v;

Syntax of putIfAbsent() method

V putIfAbsent(K key, V value)

Here the parameters are-

  • key- key with which the specified value is to be associated
  • value- value to be associated with the specified key

This method returns the previous value if key is already associated with a value or null if there was no existing mapping for the key. Method also returns null if key was previously inserted as null in the HashMap.

Note that the default implementation of the putIfAbsent() method in the Map interface makes no guarantees about synchronization or atomicity properties of this method. Implementation of putIfAbsent() in the ConcurrentHashMap guarantees atomicity.

putIfAbsent() Java examples

1. In the following example we’ll try to insert a new value with an existing key.

import java.util.HashMap;
import java.util.Map;

public class MapPutIfAbsent {

  public static void main(String[] args) {
      Map<String, String> carMap = new HashMap<String, String>();
      // Storing elements
      carMap.put("1", "Audi");
      carMap.put("2", "BMW");
      carMap.put("3", "Jaguar");
      String val = carMap.putIfAbsent("3", "Mini Cooper");
      System.out.println("Value is- " + val);
      System.out.println(carMap);
  }
}
Output
Value is- Jaguar
{1=Audi, 2=BMW, 3=Jaguar}

As you can see since the key is already present in the HashMap so the value is not rewritten. Also note that the putIfAbsent() is returning the already associated value.

2. In the following example we’ll try to insert a value with a key that doesn’t already exist.

public class MapPutIfAbsent {
  public static void main(String[] args) {
    Map<String, String> carMap = new HashMap<String, String>();
    // Storing elements
    carMap.put("1", "Audi");
    carMap.put("2", "BMW");
    carMap.put("3", "Jaguar");
    String val = carMap.putIfAbsent("4", "Mini Cooper");
    System.out.println("Value is- " + val);
    System.out.println(carMap);
  }
}
Output
Value is- null
{1=Audi, 2=BMW, 3=Jaguar, 4=Mini Cooper}

As you can see from the output value is added to the HashMap along with the new key. putIfAbsent() method returns null because there was no existing mapping for the key.

3. In the following example we’ll try to insert a value with a key as null when there is already a value with null key.

public class MapPutIfAbsent {

  public static void main(String[] args) {
    Map<String, String> carMap = new HashMap<String, String>();
      // Storing elements
      carMap.put("1", "Audi");
      carMap.put("2", "BMW");
      carMap.put("3", "Jaguar");
      carMap.put(null, "Volks Wagon");
      String val = carMap.putIfAbsent(null, "Mini Cooper");
      System.out.println("Value is- " + val);
      System.out.println(carMap);
  }
}
Output
Value is- Volks Wagon
{null=Volks Wagon, 1=Audi, 2=BMW, 3=Jaguar}

As you can see new value is inserted now since the previous value was mapped to null. Return value of the putIfAbsent() method is the previous value.

That's all for the topic Map#putIfAbsent() 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

November 22, 2021

Java Stream peek() With Examples

In this tutorial we’ll see how to use Java Stream peek() method with the help of few examples.

Syntax of peek() method in Java Stream API

Stream<T> peek(Consumer<? super T> action)

Argument passed to the peek method is of type Consumer functional interface which represents a non-interfering action to perform on the elements as they are consumed from the stream. Method returns a new Stream.

peek() is an intermediate operation which means using peek() without any terminal operation will do nothing.

Java 9 onward, if the number of elements in Stream source is known in advance then no source elements will be traversed and no intermediate operations like peek() will be evaluated. This is a performance optimization.

peek() method exists mainly to support debugging, where you want to see the elements as they flow from one operation to another with in the Stream pipeline.

Java Stream peek() examples

1. In this example peek() method is used to display the stream elements after each operation.

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamPeek {

  public static void main(String[] args) {
     List<String> tempList = Stream.of("one", "two", "three", "four", "five")
         .filter(e -> e.length() > 3)
         .peek(e -> System.out.println("Filtered value: " + e))
         .map(String::toUpperCase)
         .peek(e -> System.out.println("Mapped value: " + e))
         .collect(Collectors.toList());
     
     System.out.println(tempList);
  }
}
Output
Mapped value: THREE
Filtered value: four
Mapped value: FOUR
Filtered value: five
Mapped value: FIVE
[THREE, FOUR, FIVE]

As you can see peek() method is a good way to debug your Stream and see the results of the operation on the Stream.

2. If you don’t have a terminal operation, intermediate operations like peek() are not executed. You can see that by removing the collect() operation from the previous example.

public class StreamPeek {

  public static void main(String[] args) {
    Stream.of("one", "two", "three", "four", "five")
           .filter(e -> e.length() > 3)
           .peek(e -> System.out.println("Filtered value: " + e))
           .map(String::toUpperCase)
           .peek(e -> System.out.println("Mapped value: " + e));
  }
}
On executing it you won’t get any output.

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


You may also like

November 15, 2021

Exception Propagation in Java

In the execution of the method code, if an exception condition occurs, normal flow of the method is disrupted. In order to handle the exceptional condition an exception object is created and thrown. That exception may be handled in the method where that exception is thrown or it may be passed on to be handled by other methods in the caller stack. This process of going through the method call stack to look for an exception handler that can handle the thrown exception is known as exception propagation in Java.

Exception propagation in Java

To reach to a certain method in the code, some other methods are called in between. This list of methods is known as the method call stack.

When an exception occurs in the current method, exception handling mechanism will look for an exception handler in the current method, if not found it will go to the previous method (caller method of the current method) in the call stack and so on looking for the exception handler that can handle the thrown exception.

If no exception handler is provided for the thrown exception, default exception handler will be called to handle that exception.

Exception Propagation flow

Suppose you have a call stack of three methods method1, method2 and method3. From method1 you call method2 and method3 is called from method2.

If an exception occurs in method 3 and the exception handler is in method1 then the exception propagation in Java can be shown as follows-

exception propagation in java

Exception Propagation in Java with checked and unchecked exceptions

In case of unchecked exception it is not enforced to handle the exception using try-catch block or throws clause so exception propagation happens by default.

In case of checked exception you will have to declare the exception that are not handled with in a method by using throws keyword. That is an indication that exception has to be propagated to the caller method. If caller method wishes to propagate it further then it can also declare the thrown exceptions using the throws keyword.

Exception propagation Java example with unchecked exception

Let’s take the same method hierarchy of three methods as depicted above. Where exception occurs in method3 and propagates to method1 in search of an appropriate exception handler.

public class ExceptionPropagationDemo {
  public static void main(String[] args) {
    ExceptionPropagationDemo ep = new ExceptionPropagationDemo();
    ep.method1();
  }
  // This method forwards the exception
  void method3(){
    System.out.println("In method3");
    int[] numArr = {4,5,6};
    int number = numArr[5];
  }

  // This method forwards the exception
  void method2(){
    System.out.println("In method2");
    method3();
  }
	
  // Exception is handled in this method
  void method1(){
    try{
      System.out.println("In method1");
      method2();
    } catch(Exception e){
      System.out.println("Exception handled");
      e.printStackTrace();
    }
  }
}
Output
In method1
In method2
In method3
Exception handled
java.lang.ArrayIndexOutOfBoundsException: 5
	at com.knpcode.ExceptionPropagationDemo.method3(ExceptionPropagationDemo.java:14)
	at com.knpcode.ExceptionPropagationDemo.method2(ExceptionPropagationDemo.java:20)
	at com.knpcode.ExceptionPropagationDemo.method1(ExceptionPropagationDemo.java:27)
	at com.knpcode.ExceptionPropagationDemo.main(ExceptionPropagationDemo.java:7)

In the above code exception occurs in method3 as there is an attempt to get the value at the index 5 of an array whose length is 3. This will result in ArrayIndexOutOfBoundsException being thrown. Since method3 does not provide any exception handling mechanism so next method (method 2) is searched, there also no exception handling mechanism is found so exception propagates to method1 where it is handled. You can see the same flow in the exception trace where exception originates in method3 and propagates to method1.

Exception propagation Java example with checked exception

In case of checked exception you need to explicitly specify the exceptions using throws clause if you are not providing exception handling with in the method.

Let’s see an example of exception propagation with checked exceptions. Here in method 3 there is a code to read a file and stream is also closed both of these activities may result in checked exception. Since you are forced to handle that exception so you specify it using throws clause. Notice that method2 is not providing exception handling so there also it is specified using throws clause. That way exception propagates to method1 where it is handled.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class ExceptionPropagationDemo {
  public static void main(String[] args) {
    ExceptionPropagationDemo ep = new ExceptionPropagationDemo();
    ep.method1();
  }
  // This method forwards the exception
  void method3() throws IOException{
    System.out.println("In method3");
    BufferedReader br = null;
    try{
      br = new BufferedReader(new
          InputStreamReader(new FileInputStream(new 
              File("D:\\test1.txt"))));
    }finally{
      if(br != null)
        br.close();
    }		
  }
	
  // This method forwards the exception
  void method2() throws IOException{
    System.out.println("In method2");
    method3();
  }
	
  // Exception is handled in this method
  void method1(){
    try{
      System.out.println("In method1");
      method2();
    } catch(IOException e){
      System.out.println("Exception handled");
      e.printStackTrace();
    }
  }
}
Output
In method1
In method2
In method3
Exception handled
java.io.FileNotFoundException: D:\test1.txt (The system cannot find the file specified)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(Unknown Source)
	at java.io.FileInputStream.(Unknown Source)
	at com.knpcode.ExceptionPropagationDemo.method3(ExceptionPropagationDemo.java:22)
	at com.knpcode.ExceptionPropagationDemo.method2(ExceptionPropagationDemo.java:34)
	at com.knpcode.ExceptionPropagationDemo.method1(ExceptionPropagationDemo.java:41)
	at com.knpcode.ExceptionPropagationDemo.main(ExceptionPropagationDemo.java:13)

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


You may also like