September 30, 2023

Input from User in Python – input() function

If you have to take user input from keyboard in Python that can be done using input() function. Python input() function takes the entered value and returns it as a string once user presses Enter.

Syntax of input() function

The syntax of Python input() function is

input(msg)

Here msg is the optional string that is displayed on the console.

User input in Python example

val = input('Please enter your name: ')
print('Entered Value- ', val)
Output
Please enter your name: knpcode
Entered Value- knpcode

Input as number in Python

Note that input() function always returns entered value as string. If you want to get the value as integer or float you need to convert it explicitly.

val = input('Please enter a number: ')
# Convert to int
val = int(val)
# now use in arithmetic operation
print(val+5)
Output
Please enter a number: 8
13

You can use int() function along with the input() function to shorten the code-

val = int(input('Please enter a number: '))
# now use in arithmetic operation
print(val+5)

For float numbers you can use float() function

val = float(input('Please enter a number: '))
# now use in arithmetic operation
print(val+5)

Multiple values as input in Python

You can write separate input() functions to take more than one inputs from user. But Python provides a shorter version by using for loop along with input() function to take multiple inputs. Entered values are parsed as separate values by using split() method which considers space as delimiter by default. Therefore separate the separate inputs by space.

num1, num2, num3 = [int(x) for x in input('Please enter three integers: ').split()]
print('Sum of entered numbers-', (num1+num2+num3))
Output
Please enter three integers: 4 5 6
Sum of entered numbers- 15

That's all for the topic Input from User in Python – input() function. If something is missing or you have something to share about the topic please write a comment.


You may also like

September 29, 2023

Java String valueOf() Method With Examples

Java string valueOf() method is used to convert values of different data types into their String representations.

valueOf() methods in String class

valueOf() method in Java String class is overloaded and has following variants-

  • String valueOf(boolean b)- Returns the string representation of the boolean argument. If the argument is true, a string equal to "true" is returned; otherwise, a string equal to "false" is returned.
  • String valueOf(char c)- Returns the string representation of the char argument.
  • String valueOf(int i)- Returns the string representation of the int argument.
  • String valueOf(long l)- Returns the string representation of the long argument.
  • String valueOf(float f)- Returns the string representation of the float argument.
  • String valueOf(double d)- Returns the string representation of the double argument.
  • String valueOf(char[] data)- Returns the string representation of the char array argument.
  • String valueOf(char[] data, int offset, int count)- Returns the string representation of a specific subarray of the char array argument.
  • String valueOf(Object obj)- Returns the string representation of the Object argument.

Java string valueOf() examples

valueOf() methods are handy utility methods to convert different data types to String so let’s see examples by passing different data types.

String.valueOf(boolean b)

This variant of valueOf() method takes a boolean value as argument and returns a String.

public class StringValueOf {
  public static void main(String[] args) {
    boolean flag1 = true;
    boolean flag2 = false;
    String str1 = String.valueOf(flag1);
    String str2 = String.valueOf(flag2);
    System.out.println(str1);
    System.out.println(str2);
  }
}
Output
true
false

String.valueOf(char c)

This variant of valueOf() method takes a character as argument and returns its String representation.

public class StringValueOf {
  public static void main(String[] args) {
    char c = 'a';
    String str = String.valueOf(c);
    System.out.println(str);
  }
}
Output
a

String.valueOf(int i)

In this variant of valueOf() method int is passed as argument and its String representation is returned.

public class StringValueOf {
  public static void main(String[] args) {
    int i = 89;
    String str = String.valueOf(i);
    System.out.println(str);
  }
}
Output
89

String.valueOf(long l)

In this variant of valueOf() method long value is passed as argument and its String representation is returned.

public class StringValueOf {
  public static void main(String[] args) {
    long l = 8978L;
    String str = String.valueOf(l);
    System.out.println(str);
  }
}
Output
8978

String.valueOf(float f)

In this variant of valueOf() method float value is passed as argument and its String representation is returned.

public class StringValueOf {
  public static void main(String[] args) {
    float f = 237.897f;
    String str = String.valueOf(f);
    System.out.println(str);
  }
}
Output
237.897

String.valueOf(double d)

In this variant of valueOf() method double value is passed as argument and its String representation is returned.

public class StringValueOf {
  public static void main(String[] args) {
    double d = 135.6814d;
    String str = String.valueOf(d);
    System.out.println(str);
  }
}
Output
135.6814

String.valueOf(char[] data)

This variant of valueOf() method returns the String representation of the passed char array argument.

public class StringValueOf {
  public static void main(String[] args) {
    char[] c = {'a', 'b', 'c', 'd'};
    String str = String.valueOf(c);
    System.out.println(str);
  }
}
Output
abcd

String.valueOf(char[] data, int offset, int count)

In this variant of the valueOf() method you can specify the range for the subarray that is converted to the String. The offset argument is the index of the first character of the subarray. The count argument specifies the length of the subarray.

public class StringValueOf {
  public static void main(String[] args) {
    char[] c = {'a', 'b', 'c', 'd'};
    String str = String.valueOf(c, 1, 2);
    System.out.println(str);
  }
}
Output
bc

String.valueOf(Object obj)

class Employee{
  int id;
  String name;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  @Override
  public String toString() {
    return "id= " + getId() + " Name= " + getName();
  }	
}

public class StringValueOf {
  public static void main(String[] args) {
    Employee emp = new Employee();
    emp.setId(1);
    emp.setName("Stuart");
    String str = String.valueOf(emp);
    System.out.println(str);
  }
}
Output
id= 1 Name= Stuart

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


You may also like

September 27, 2023

Dispatch Actions From createAsyncThunk - React Example

In the post createAsyncThunk in Redux + React Example we have seen how to use createAsyncThunk to write side effects when using Redux. In this post we'll see how to dispatch an action from the callback function of createAsyncThunk.

How createAsyncThunk works

createAsyncThunk will generate three Redux action creators for three states your asynchronous call may be in-

  1. pending
  2. fulfilled
  3. rejected

createAsyncThunk function abstracts the approach for handling async request lifecycles which is either resolved or rejected.

  • Dispatches the fulfilled action with the promise value as action.payload when the promise resolved successfully.
  • If the promise resolved with an error, dispatches the rejected action.

In your state slice you use extraReducers to handle dispatched actions that are created by createAsyncThunk. Based on the action that is dispatched (pending, fulfilled, rejected) you can update the state stored in the store.

Dispatch from createAsyncThunk

In your application, rather than handling the state in these action creators, you may want to dispatch action to the same slice or to another slice. That's what we'll see in this post how to dispatch an action inside the callback function of createAsyncThunk.

createAsyncThunk function accepts three parameters-

  1. A Redux action type string which signifies the name of the action. Convention is to use "slice name/action name" as the action name for example "posts/fetchPostData".
  2. A callback function where asynchronous logic is written and the function returns a promise containing the result of asynchronous logic.

    The callback function will be called with two arguments:

    • arg: A single value, containing the first parameter that was passed to the thunk action creator when it was dispatched. For example, you can pass an ID to fetch data based on that ID, data that has to be saved.
    • thunkAPI: an object containing all of the parameters that are normally passed to a Redux thunk function. Some of the main ones are-
      • dispatch: the Redux store dispatch method.
      • getState: the Redux store getState method.
      • rejectWithValue(value, [meta]): rejectWithValue is a utility function that you can return (or throw) in your action creator to return a rejected response with a defined payload and meta.
      • fulfillWithValue(value, meta): fulfillWithValue is a utility function that you can return in your action creator to fulfill with a value while having the ability of adding to fulfilledAction.meta.

As you can see callback function takes two arguments one of them is thunkAPI which is an object having one of the properties as dispatch. This Redux store dispatch() method can be used to dispatch actions.

For example-

createAsyncThunk(
    'postItems/addPost',
    async(post, {dispatch}) => {
        try{
            //async logic..
            ...
            // dispatch success notification action 
            dispatch(notificationActions.showNotification({
                status: 'Success',
                message: 'Post data successfully inserted, title is: ' + data.title
              })
            );
        } catch(error){
            // dispatch error notification action 
            dispatch(notificationActions.showNotification({
                status: 'Error',
                message: 'Error while inserting post ' + error.message
              })); 
        }
    }
);

createAsyncThunk React example

This redux-thunk example uses jsonplaceholder API to fetch posts and add new post. These async fetch requests are done in createAsyncThunk functions.

1. Create state slices

We'll have two state slices one for storing post state and another for notification state.

src\slice\post-slice.js

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { notificationActions } from "./notification-slice";
const postSlice = createSlice({
    name: 'postItems',
    initialState: {
        posts: []
    },
    reducers: {
        refreshPosts: (state, action) => {
            state.posts = action.payload
        },
        addPost: (state, action) => {
            const newPost = action.payload;
            state.posts.push({
                id: newPost.id,
                title: newPost.title,
                body: newPost.body,
                userId: newPost.userId
            })
        }
     },

});

export const fetchPostData = createAsyncThunk(
    'postItems/fetchPostData',
    async (_, {dispatch}) => {            
        try{
            const response = await fetch('https://jsonplaceholder.typicode.com/posts');
            if(!response.ok){
                throw new Error('Fetching posts failed..');
            }
            const data = await response.json();
            dispatch(postActions.refreshPosts(data));
        } catch(error){
            console.log("Error in fetching " + error.message);
            dispatch(notificationActions.showNotification({
                status: 'Error',
                message: 'Error while fetching posts ' + error.message
            }));
        }
    }
);

export const addPostData = createAsyncThunk(
    'postItems/addPost',
    async(post, {dispatch}) => {
        try{
            const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
                method: 'POST',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(post)
            });
            if(!response.ok){
                throw new Error('Inserting new posts failed.');
            }
            const data = await response.json();
            dispatch(notificationActions.showNotification({
                status: 'Success',
                message: 'Post data successfully inserted, title is: ' + data.title
              })
            );
        } catch(error){
            dispatch(notificationActions.showNotification({
                status: 'Error',
                message: 'Error while inserting post ' + error.message
              }));      
        }
    }
);

export const postActions = postSlice.actions;
export default postSlice.reducer;

Some of the important points about this state slice are-

  1. Name of the slice is postItems.
  2. Initial state value is an empty array meaning no posts.
  3. There are two reducer functions refreshPosts and addPosts, in those functions there is no async logic (no side effect).
  4. There are two createAsyncThunk functions with names as 'postItems/fetchPostData' and 'postItems/addPost'
  5. In those createAsyncThunk functions there are callback functions to make asynchronous calls to fetch all posts and to add a post respectively.
  6. If call to fetch posts is successful then an action is dispatched from the callback function to update the posts state. In case of error notificationAction is dispatched. Same way with the call to add new post. A notification action is dispatched with success or error message in case of success or error.
  7. If first argument is not passed to the callback function only second argument then it has to be in the following format.
    async (_, {dispatch}) => { }
    

src\slice\notification-slice.js

import { createSlice } from "@reduxjs/toolkit";

const notificationSlice = createSlice({
    name: 'notification',
    initialState: {notification: null},
    reducers: {
        showNotification: (state, action) => {
            state.notification = {
                status: action.payload.status,
                message: action.payload.message
            };
        }
    }

})

export const notificationActions = notificationSlice.actions;
export default notificationSlice.reducer;

2. Setting up a store with Reducers

src\store\postStore.js

import { configureStore } from "@reduxjs/toolkit";
import postReducer from "../slice/post-slice";
import notificationReducer from "../slice/notification-slice";

const store = configureStore({
    reducer: {
        post: postReducer,
        notification: notificationReducer
    }
});

3. Provide store to React

React Redux includes a <Provider /> component, which makes the Redux store available to the React app. We'll wrap <App /> component with the Provider which guarantees that the store provided with this Provider is available to App component and all its child components. That change can be done in index.js file.

src\index.js

import { Provider } from 'react-redux';
import store from './store/postStore';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}><App /></Provider>
  </React.StrictMode>
);

4. Components

For fetching posts and displaying them there are two components Posts.js and PostItem.js.

For showing notification there is Notification.js.

src\components\Notification\Notification.js

const Notification = (props) => {
  return (
    <div className="alert alert-primary" role="alert">
      <p>{props.status} : {props.message}</p>
    </div>
  );
};

export default Notification;

Note that Bootstrap classes are used to show alert notification.

src\components\Post\Posts.js

This component dispatches thunk function in useEffect() hook and then loops over the fetched posts to display them using PostItem component.

import { Fragment, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux"
import { fetchPostData } from "../../slice/post-slice";
import Notification from "../Notification/Notification";
import PostItem from "./PostItem";


const Posts = () => {
    const posts = useSelector(state => state.post.posts);
    const notification = useSelector(state => state.notification.notification); 
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(fetchPostData());
    }, [dispatch])
    
    return (
        <Fragment>
             { notification && <Notification status={notification.status} 
            title={notification.title} message={notification.message}/> }
            <h2>Posts</h2>
            <ul>
                {
                    posts.map(post=> (
                        <PostItem key={post.id} post={post}></PostItem>
                    )
                )}
            </ul>
        </Fragment>
    );
}

export default Posts;

src\components\Post\PostItem.js

const PostItem = (props) => {
    return (
        <li>
            <span>User: {props.post.userId}</span>
            <h2>{props.post.title}</h2> 
            <span>{props.post.body}</span>
        </li>
    );
}

export default PostItem;

I can test Posts component by adding this element to App.js

function App() {
return (
    <div className="App">
        <Posts />
    </div>
  );
}
createAsyncThunk - React Example

When there is an error

dispatch action from createAsyncThunk

Adding post

For adding new post following component is used.

src\components\Post\AddPost.js

import { Fragment } from "react";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { addPostData } from "../../slice/post-slice";
import Notification from "../Notification/Notification";

const AddPost = () => {
    const notification = useSelector(state => state.notification.notification);
    const dispatch = useDispatch();
    const [formField, setState] = useState({
        title: '',
        body: '',
        userId: ''
    });
    const handleInputChange = (event) => {
        const target = event.target;
        const value = target.value;
        const name = target.name;
    
        setState((prevState) => {
            return {...prevState, [name]: value};
        });
    }

    const formSubmitHandler = (event) => {
        event.preventDefault();
        dispatch(addPostData({
            title: formField.title,
            body: formField.body,
            userId: formField.userId
        }));
    }

    return(
        <Fragment>
            { notification && <Notification status={notification.status} 
            title={notification.title} message={notification.message}/> }
            <form onSubmit={formSubmitHandler}>
                Title: <input type="text" placeholder="Enter Title" name="title" onChange={handleInputChange}></input>
                Body: <input type="text" placeholder="Enter Post Content" name="body" onChange={handleInputChange}></input>
                User ID: <input type="number" placeholder="Enter User ID" name="userId" onChange={handleInputChange}></input>
                <button type="submit" onClick={formSubmitHandler}>Add Post</button>
            </form>
        </Fragment>
        
    );

}

export default AddPost;

That's all for the topic Dispatch Actions From createAsyncThunk - React Example. If something is missing or you have something to share about the topic please write a comment.


You may also like

September 25, 2023

createAsyncThunk in Redux + React Example

In the post Redux Thunk in React With Examples we saw a way to write asynchronous logic while using Redux. One of the rules of the reducers is that reducers must not do any asynchronous logic or any other side effects. Redux-thunk is the most common async middleware which lets you write plain functions that may contain async logic directly. Another way to write asynchronous logic with Redux is to use createAsyncThunk() function.

createAsyncThunk in redux-thunk

By using createAsyncThunk() function, it becomes easy to use Promise or async/await (which also returns a Promise). This function abstracts the approach for handling async request lifecycles which is either resolved or rejected.

createAsyncThunk function accepts three parameters-

  1. A Redux action type string which signifies the name of the action. Convention is to use "slice name/action name" as the action name for example "posts/fetchPostData".
  2. A callback function where asynchronous logic is written and the function returns a promise containing the result of asynchronous logic.

    The callback function will be called with two arguments:

    • arg: A single value, containing the first parameter that was passed to the thunk action creator when it was dispatched. For example, you can pass an ID to fetch data based on that ID, data that has to be saved.
    • thunkAPI: an object containing all of the parameters that are normally passed to a Redux thunk function. Some of the main ones are-
      • dispatch: the Redux store dispatch method.
      • getState: the Redux store getState method.
      • rejectWithValue(value, [meta]): rejectWithValue is a utility function that you can return (or throw) in your action creator to return a rejected response with a defined payload and meta.
      • fulfillWithValue(value, meta): fulfillWithValue is a utility function that you can return in your action creator to fulfill with a value while having the ability of adding to fulfilledAction.meta.
  3. Options- An object with the optional fields. Some of the fields are as given below.
    • condition(arg, { getState, extra } ): boolean | Promise<boolean>: a callback that can be used to skip execution of the payload creator and all action dispatches, if desired. See Canceling Before Execution for a complete description.
    • dispatchConditionRejection: if condition() returns false, the default behavior is that no actions will be dispatched at all. If you still want a "rejected" action to be dispatched when the thunk was canceled, set this flag to true.

Return value of createAsyncThunk

createAsyncThunk will generate three Redux action creators for three states your asynchronous call may be in-

  1. pending
  2. fulfilled
  3. rejected

Each of these action creators will be attached to the thunk action creator which is returned by the createAsyncThunk.

For example, if we take the same "fetchPostData" example as mentioned above following functions will be generated by createAsyncThunk.

  • fetchPostData.pending, an action creator that dispatches 'posts/fetchPostData/pending' action
  • fetchPostData.fulfilled, an action creator that dispatches 'posts/fetchPostData/fulfilled' action
  • fetchPostData.rejected, an action creator that dispatches 'posts/fetchPostData/rejected' action

createAsyncThunk flow

When createAsyncThunk is dispatched the thunk will-

  1. Initially dispatch the pending action.
  2. Call the callback function where we have asynchronous logic and wait for the returned promise to settle.
  3. When the promise settles:
    • If the promise resolved successfully, dispatch the fulfilled action with the promise value as action.payload
    • if the promise resolved with a rejectWithValue(value) return value, dispatch the rejected action with the value passed into action.payload and 'Rejected' as action.error.message.
    • if the promise failed and was not handled with rejectWithValue, dispatch the rejected action with a serialized version of the error value as action.error
  4. Return a fulfilled promise containing the final dispatched action (either the fulfilled or rejected action object).

extraReducers

In your state slice you use extraReducers to handle dispatched actions that are created by createAsyncThunk. Based on the action that is dispatched (pending, fulfilled, rejected) you will update the stored state.

You can reference the action creators in extraReducers using either the object key notation or the "builder callback" notation.

Using object key notation-

createSlice({
    name: 'postItems',
    initialState: {},
    reducers: {},
    extraReducers: {
       [fetchPostData.pending]: (state, action) => {},
       [fetchPostData.fulfilled]: (state, action) => {},
       [fetchPostData.rejected]: (state, action) => {}
    }
})

Using builder callback notation-

createSlice({
    name: 'postItems',
    initialState: {},
    reducers: {},
    extraReducers: (builder) => {
        builder
        .addCase(fetchPostData.pending, (state, action) => {})
        .addCase(fetchPostData.fulfilled, (state, action) => {})
        .addCase(fetchPostData.rejected, (state, action) => {})
    }
})

createAsyncThunk React example

This redux-thunk example with createAsyncThunk uses jsonplaceholder API to fetch posts and add new post.

1.Create state slice

We have one state slice for storing post state.

src\slice\post-slice.js

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";

const postSlice = createSlice({
    name: 'postItems',
    initialState: {
        posts: [],
        status: "idle", 
        error: null
    },
    reducers: {},
    extraReducers: (builder) => {
        builder
        .addCase(fetchPostData.pending, (state, action) => {
            state.status = "Loading";
        })
        .addCase(fetchPostData.fulfilled, (state, action) => {
            state.status = "Success";
            state.posts = action.payload;
        })
        .addCase(fetchPostData.rejected, (state, action) => {
            state.status = "Error";
            state.error = action.payload;
        })
        .addCase(addPostData.fulfilled, (state, action) => {
            state.status = "Success";
            const newPost = action.payload;
            state.posts.push({
                id: newPost.id,
                title: newPost.title,
                body: newPost.body,
                userId: newPost.userId
            })
        })
        .addCase(addPostData.rejected, (state, action) => {
            state.status = "Error";
            state.error = action.payload;
        })
    }

});

export const fetchPostData = createAsyncThunk(
    'postItems/fetchPostData',
    async (_, {rejectWithValue}) => {            
        try{
            const response = await fetch('https://jsonplaceholder.typicode.com/posts');
            if(!response.ok){
                throw new Error('Fetching posts failed..');
            }
            const data = await response.json();
            return data;    
        } catch(error){
            console.log("Error in fetching " + error.message);
            return rejectWithValue(error.message);
            //return error.message;

        }
    }
);

export const addPostData = createAsyncThunk(
    'postItems/addPost',
    async(post, {rejectWithValue}) => {
        try{
            const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
                method: 'POST',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(post)
            });
            if(!response.ok){
                throw new Error('Inserting new posts failed.');
            }
            const data = await response.json();
            return data;
        } catch(error){
            return rejectWithValue(error.message);         
        }
    }
);

export default postSlice.reducer;

Some of the important points about this state slice are-

  1. Name of the slice is postItems.
  2. Initial state value contains an empty array meaning no posts, state as "idle" and error as null.
  3. There are two createAsyncThunk functions with names as 'postItems/fetchPostData' and 'postItems/addPost'
  4. In those createAsyncThunk functions there are callback functions to make asynchronous calls to fetch all posts and to add a post respectively.
  5. In case of error, rejectWithValue utility function is returned.
  6. If second argument to the callback function is rejectWithValue and there is no first argument then it has to be in the following format.
    async (_, {rejectWithValue}) => { }
    

2. Setting up a store with Reducers

src\store\postStore.js
import { configureStore } from "@reduxjs/toolkit";
import postReducer from "../slice/post-slice";
import notificationReducer from "../slice/notification-slice";

const store = configureStore({
    reducer: {
        post: postReducer,
    }
});

export default store;

3. Provide store to React

React Redux includes a <Provider /> component, which makes the Redux store available to the React app. We'll wrap <App /> component with the Provider which guarantees that the store provided with this Provider is available to App component and all its child components. That change can be done in index.js file.

src\index.js
import { Provider } from 'react-redux';
import store from './store/postStore';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}><App /></Provider>
  </React.StrictMode>
);

Components

For fetching posts and displaying them there are two components Posts.js and PostItem.js.

For showing notification there is Notification.js.

src\components\Notification\Notification.js
const Notification = (props) => {
  return (
    <div className="alert alert-primary" role="alert">
      <p>{props.status} : {props.message}</p>
    </div>
  );
};

export default Notification;

Here Bootstrap classes are used to show alert notification.

src\components\Post\Posts.js

import { Fragment, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux"
import { fetchPostData } from "../../slice/post-slice";
import Notification from "../Notification/Notification";
import PostItem from "./PostItem";

const Posts = () => {
    const posts = useSelector(state => state.post.posts);
    const status = useSelector(state => state.post.status);
    const error = useSelector(state => state.post.error);
    let uiContent;    
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(fetchPostData());
    }, [dispatch])
    
    if(status === "Success"){
        uiContent = 

            <ul>{posts.map(post => (
                    <PostItem key={post.id} post={post}></PostItem>
                ))}
            </ul>;            

    }else if(status === "Error"){
        uiContent = <Notification status={status} message={error}/>
    }else if(status === "Loading"){
        uiContent = <Notification status={status} message="Loading..."/>
    }
    return (
        <Fragment>
            <h2>Posts</h2>
            {uiContent}
       </Fragment>
    );
}
export default Posts;

This component dispatches function in useEffect() hook, based on the updated status it then loops over the fetched posts to display them using PostItem component or show the appropriate notification message.

src\components\Post\PostItem.js

const PostItem = (props) => {
    return (
        <li>
            <span>User: {props.post.userId}</span>
            <h2>{props.post.title}</h2> 
            <span>{props.post.body}</span>
        </li>
    );
}

export default PostItem;

I can test Posts component by adding this element to App.js

function App() {
return (
    <div className="App">
        <Posts />
    </div>
  );
}
createAsyncThunk react

When there is an error

createAsyncThunk in Redux

Adding post

For adding new post following component is used.

src\components\Post\AddPost.js

import { Fragment } from "react";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { addPostData } from "../../slice/post-slice";
import Notification from "../Notification/Notification";

const AddPost = () => {
    const status = useSelector(state => state.post.status);
    const error = useSelector(state => state.post.error);
    let uiContent;
    const dispatch = useDispatch();
    const [formField, setState] = useState({
        title: '',
        body: '',
        userId: ''
    });
    const handleInputChange = (event) => {
        const target = event.target;
        const value = target.value;
        const name = target.name;
    
        setState((prevState) => {
            return {...prevState, [name]: value};
        });
    }

    const formSubmitHandler = (event) => {
        event.preventDefault();
        dispatch(addPostData({
            title: formField.title,
            body: formField.body,
            userId: formField.userId
        }));
    }
    if(status === "Success"){
        uiContent = <Notification status={status} message="Post successfully inserted"/>


    }else if(status === "Error"){
        uiContent = <Notification status={status} message={error}/>
    }
    return(
        <Fragment>
            { uiContent }
            <form onSubmit={formSubmitHandler}>
                Title: <input type="text" placeholder="Enter Title" name="title" onChange={handleInputChange}></input>
                Body: <input type="text" placeholder="Enter Post Content" name="body" onChange={handleInputChange}></input>
                User ID: <input type="number" placeholder="Enter User ID" name="userId" onChange={handleInputChange}></input>
                <button type="submit" onClick={formSubmitHandler}>Add Post</button>
            </form>
        </Fragment>
        
    );
}

export default AddPost;

Points to observe in the above code are-

  1. Uses useState() hook to get form fields state.
  2. At the click of "Add Post" button, formSubmitHandler() function is called where thunk function to add post is dispatched.

Source- https://redux-toolkit.js.org/api/createAsyncThunk

That's all for the topic createAsyncThunk in Redux + React Example. If something is missing or you have something to share about the topic please write a comment.


You may also like

September 24, 2023

Redux Thunk in React With Examples

In Redux Toolkit in React With Examples we saw how to use Redux in React for storing global state. In this tutorial we'll see what is Thunk in Redux and how to use redux-thunk with React.

What is Thunk in Redux

In terms of Redux, thunk is a pattern of writing function that takes dispatch and getState as arguments so it can interact with Redux store using dispatch and getState.

Thunk functions are not directly called by application code, you will dispatch them.

In Redux you normally use action creators to generate action objects for dispatching, you don't write action objects yourself. Same way, you will normally use thunk action creators to generate the thunk functions that are dispatched. Think of thunk action creator as a function that returns a thunk function.

//thunk action creator
export const fetchPostData = (postId) => {
   //thunk function
  return async (dispatch) => {
      const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`);
      const data = await response.json();
      dispatch(postActions.refreshPosts(fetchedPosts));
}

Then you may call it in your component

function PostComponent({ postId }) {
  const dispatch = useDispatch()

  const onGetPostClicked = () => {
    dispatch(fetchPostData(postId))
  }
}

Why Thunks

You must be thinking why go through all this extra logic of having function with in a function then dispatch that thunk action creator. Why not directly dispatch actions.

1. One of the most important use cases for thunk is to use async logic. One of the rules of the reducers is that reducers must not do any asynchronous logic or any other side effects but real applications require logic that has side effects. You can think of thunk as a function where you can have async logic but it can also facilitate interaction with the Redux store.

redux-thunk is the most common async middleware which lets you write plain functions that may contain async logic directly. Redux Toolkit's configureStore function automatically sets up the thunk middleware by default so you don't need to write applyMiddleware() explicitly when creating store.

Redux library recommends using thunks as a standard approach for writing async logic with Redux.

2. Another benefit of using thunk is to keep your components leaner having only the presentation logic. For example, you are supposed to get some data when the component renders and you want to use useEffect() hook. Rather than writing the whole logic of fetching data, checking for errors and dispatching action with in useEffect() in that component you can move this logic in a thunk function. From your useEffect() hook you just dispatch thunk action creator.

3. You can also use thunks for synchronous logic as per Redux library documentation "Thunks are best used for complex synchronous logic, and simple to moderate async logic such as making a standard AJAX request and dispatching actions based on the request results."

Redux-thunk React example

Let's try to make things clearer with an example. This redux-thunk example uses jsonplaceholder API to fetch posts and add new post. These async fetch requests are done in thunk functions.

1. Create state slices

We'll have two state slices one for storing post state and another for notification state.

src\slice\post-slice.js

import { createSlice } from "@reduxjs/toolkit";
import { notificationActions } from "./notification-slice";


const postSlice = createSlice({
    name: 'postItems',
    initialState: {
        posts: []
    },
    reducers: {
        refreshPosts: (state, action) => {
            state.posts = action.payload
        },
        addPost: (state, action) => {
            const newPost = action.payload;
            state.posts.push({
                id: newPost.id,
                title: newPost.title,
                body: newPost.body,
                userId: newPost.userId
            })
        }
    }

});

// thunk action creator
export const fetchPostData = () => {
    return async (dispatch) => {
        const postData = async () => {
            const response = await fetch('https://jsonplaceholder.typicode.com/posts');
            if(!response.ok){
                throw new Error('Fetching posts failed.');
            }
            const data = await response.json();
            return data;
        }
        try{
            const fetchedPosts = await postData();
            dispatch(postActions.refreshPosts(fetchedPosts));

        } catch(error){
            dispatch(notificationActions.showNotification({
                status: 'Error',
                message: 'Error while fetching posts ' + error.message
            }));
        }
    }
}

// thunk action creator
export const addPostData = (post) => {
    return async (dispatch) => {
        const insertPost = async () => {
            const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
                method: 'POST',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(post)
            });
            if(!response.ok){
                throw new Error('Inserting new posts failed.');
            }
            const data = await response.json();
            console.log(data);
            return data;
        }
        try{
            const insertedPost = await insertPost();
            dispatch(notificationActions.showNotification({
                status: 'Success',
                message: 'Post data successfully inserted, title is: ' + insertedPost.title
              })
            );

        } catch(error){
            dispatch(notificationActions.showNotification({
                status: 'Error',
                message: 'Error while inserting post' + error.message
              }));
            
        }
    }
}
export const postActions = postSlice.actions;
export default postSlice.reducer;

In the code for slice, points to observe are-

  1. Name to identify the slice is postItems.
  2. Initial state value is an empty array meaning no posts.
  3. There are two reducer functions refreshPosts and addPosts in those functions there is no async logic (no side effect).
  4. There are two thunk action creators that’s where fetch is used to get post data or to add post data. From thunk functions there is interaction with reducers by dispatching actions.
    dispatch(postActions.refreshPosts(fetchedPosts));
    
    dispatch(notificationActions.showNotification({
                status: 'Error',
                message: 'Error while fetching posts ' + error.message
    }));
    
  5. Export the reducers and actions so that they can be used where needed.
    export const postActions = postSlice.actions;
    export default postSlice.reducer;
    

src\slice\notification-slice.js

import { createSlice } from "@reduxjs/toolkit";
const notificationSlice = createSlice({
    name: 'notification',
    initialState: {notification: null},
    reducers: {
        showNotification: (state, action) => {
            state.notification = {
                status: action.payload.status,                
                message: action.payload.message
            };
        }
    }
})

export const notificationActions = notificationSlice.actions;
export default notificationSlice.reducer;

2. Add reducers to the store

src\store\postStore.js

import { configureStore } from "@reduxjs/toolkit";
import postReducer from "../slice/post-slice";
import notificationReducer from "../slice/notification-slice";

const store = configureStore({
    reducer: {
        post: postReducer,
        notification: notificationReducer
    }
});

export default store;

3. Provide store to React

React Redux includes a <Provider /> component, which makes the Redux store available to the React app. We'll wrap <App /> component with the Provider which guarantees that the store provided with this Provider is available to App component and all its child components. That change can be done in index.js file.

src\index.js

import { Provider } from 'react-redux';
import store from './store/postStore';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}><App /></Provider>
  </React.StrictMode>
);

4. Using thunk in Components

For fetching posts and displaying them there are two components Posts.js and PostItem.js.

For showing notification there is Notification.js.

src\components\Notification\Notification.js

const Notification = (props) => {
  return (
    <div className="alert alert-primary" role="alert">
      <p>{props.status} : {props.message}</p>
    </div>
  );
};

export default Notification;

Here Bootstrap classes are used to show alert notification.

src\components\Post\Posts.js

This component dispatches thunk function in useEffect() and then loops over the fetched posts to display them using PostItem component.

import { Fragment, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux"
import { fetchPostData } from "../../slice/post-slice";
import Notification from "../Notification/Notification";
import PostItem from "./PostItem";

const Posts = () => {
    const posts = useSelector(state => state.post.posts);
    const notification = useSelector(state => state.notification.notification);
    
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(fetchPostData());
    }, [dispatch])
    
    return (
        <Fragment>
             { notification && <Notification status={notification.status} 
            title={notification.title} message={notification.message}/> }
            <h2>Posts</h2>
            <ul>
                {
                    posts.map(post=> (
                        <PostItem key={post.id} post={post}></PostItem>
                    )
                )}
            </ul>
        </Fragment>
    );
}

export default Posts;

Points to observe in the above code are-

  1. useSelector() hooks allows you to extract data from the Redux store state. useDispatch() hook is used to dispatch actions. So, these hooks are imported from react-redux
  2. Using useSelector() get the post state and notification state from the store.
  3. In useEffect() hook dispatch thunk action creator which in turn executes thunk action with async logic. Once posts are fetched, dispatch action to modify state array (refer fetchPostData in post-slice.js) or dispatch action to notification in case of error. Once state changes Posts component is re-rendered to show posts.
  4. There is also conditional rendering of notification if notification is not null.

src\components\Post\PostItem.js

const PostItem = (props) => {
    return (
        <li>
            <span>User: {props.post.userId}</span>
            <h2>{props.post.title}</h2> 
            <span>{props.post.body}</span>
        </li>
    );
}

export default PostItem;

I can test Posts component by adding this element to App.js

function App() {
return (
    <div className="App">
        <Posts />
    </div>
  );
}
redux thunk

If I just change the URL to get some error-

const response = await fetch('https://jsonplaceholder.typicode.com/pos');
redux thunk react example

Adding post

For adding new post following component is used.

src\components\Post\AddPost.js

import { Fragment } from "react";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { addPostData } from "../../slice/post-slice";
import Notification from "../Notification/Notification";
const AddPost = () => {
    const notification = useSelector(state => state.notification.notification);
    const dispatch = useDispatch();
    const [formField, setState] = useState({
        title: '',
        body: '',
        userId: ''
    });
    const handleInputChange = (event) => {
        const target = event.target;
        const value = target.value;
        const name = target.name;
    
        setState((prevState) => {
            return {...prevState, [name]: value};
        });
    }

    const formSubmitHandler = (event) => {
        event.preventDefault();
        dispatch(addPostData({
            title: formField.title,
            body: formField.body,
            userId: formField.userId
        }));
    }
    return(
        <Fragment>
            { notification && <Notification status={notification.status} 
            title={notification.title} message={notification.message}/> }
            <form onSubmit={formSubmitHandler}>
                Title: <input type="text" placeholder="Enter Title" name="title" onChange={handleInputChange}></input>
                Body: <input type="text" placeholder="Enter Post Content" name="body" onChange={handleInputChange}></input>
                User ID: <input type="number" placeholder="Enter User ID" name="userId" onChange={handleInputChange}></input>
                <button type="submit" onClick={formSubmitHandler}>Add Post</button>
            </form>
        </Fragment>
        
    );
}
export default AddPost;

Points to observe in the above code are-

  1. Uses useState() hook to get form fields state.
  2. At the click of “Add Post” button, formSubmitHandler() function is called where thunk function to add post is dispatched.
  3. If you notice in post-slice from thunk function actions are dispatched to change notification state.
redux-thunk react

Source- https://redux.js.org/usage/writing-logic-thunks

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


You may also like

September 23, 2023

Redux Toolkit in React With Examples

In this tutorial we'll see an introduction of Redux Toolkit and how to use it with React application.

In the post Redux in React With Examples we saw how you can create store using Redux and react-redux library. Though that is not the suggested way to create redux store but I'll suggest to go through that post to get a better idea of how Redux works. With the old way you generally have to write most of the logic yourself so it gives you a better understanding of what is a store, reducer and action. But the suggested way now is to use configureStore() provided by @reduxjs/toolkit library so let's try to understand how that works.

Using Redux toolkit

Though Redux library helps in managing global state and making state management more efficient but you may still experience the following problems.

  1. As the complexity of your project increases complexity of Redux also increases.
  2. Writing reducers and actions become more complex and their number also increases with bigger applications.
  3. State object may become big which results in keeping state immutable quite a complex task.

In order to address these issues and making it more convenient to work with Redux, the same team developed Redux toolkit. With Redux toolkit you can say that some of the steps that were done manually with Redux are now automatically derived. It also makes it more convenient to modify the stored state without worrying about its immutability as Redux toolkit uses immer library which takes care of state immutability behind the scene rather than you ensuring it.

The Redux Toolkit package is intended to be the standard way to write Redux logic.

Using @reduxjs/toolkit with react

Let's try to create the same counter application using Redux toolkit which was done in this post using Redux.

1. Install packages

If you already have a React application just navigate to the app base folder and run the following command to install Redux toolkit

npm install @reduxjs/toolkit react-redux

react-redux is the React binding library for Redux.

2. Create store

src\store\tkStore.js

import { configureStore } from "@reduxjs/toolkit";


const store = configureStore({
    reducer: { } // that's where we'll add reducer
})

export default store;

With Redux toolkit you start using configureStore() to create store rather than createStore() used with Redux.

configureStore() is an abstraction over the standard Redux createStore function that adds good defaults to the store setup for a better development experience.

configureStore accepts a single configuration object parameter, with many options. Options of interest to us initially are-

  • reducer- To accept reucer functions.
  • devTools- To indicate whether configureStore should automatically enable support for the Redux DevTools browser extension. Defaults to true.

For more details you can see the API- https://redux-toolkit.js.org/api/configureStore

3. Provide store to React

React Redux includes a <Provider /> component, which makes the Redux store available to the React app. We'll wrap <App /> component with the Provider which guarantees that the store provided with this Provider is available to App component and all its child components. That change can be done in index.js file.

import { Provider } from 'react-redux';
import store from './store/tkStore';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}><App /></Provider>
  </React.StrictMode>
);

4. Create a state slice

You can import the createSlice API from Redux Toolkit. This is the most important part as with slice you can write reducer function and actions with in the slice.

src\slice\counterSlice.js

import { createSlice } from "@reduxjs/toolkit";

const counterSlice = createSlice({
    name: 'counter',
    initialState: {value: 0},
    reducers: {
        increment: (state) => {
            state.value++;
        }, 
        decrement: (state) => {
            state.value--;
        },
        increaseByValue: (state, action) => {
            state.value += action.payload;
        }
    
    }
});

export const counterActions = counterSlice.actions;
export default counterSlice.reducer;

Some important points to note here are-

  • Creating a slice requires a name to identify the slice, which is given as ‘counter’ here.
    name: 'counter',
    
  • Slice also needs initial state value.
    initialState: {value: 0},
    
  • You can have one or more reducer functions to define how the state can be updated. You can think of reducer as a map where key is the action name and the value is the logic to update state. For example, with this piece of code.
    increment: (state) => {
                state.value++;
            }, 
    
    
    Redux generates an action named 'increment'. With the use of createSlice Redux toolkit makes it easier to define reducers and actions, you also don't need condition statements (if or switch) to determine the correct action type.
  • Another very important thing is how state is changed. It looks like, now we are mutating state rather than creating a new state altogether.
     state.value++;
    
    This is permitted with Redux toolkit because it uses immer as explained already.
  • Export the reducers and actions so that they can be used where needed.
    export const counterActions = counterSlice.actions;
    export default counterSlice.reducer;
    
    You can also use object destructuring to export the generated action creators separately.
    export const { increment, decrement, increaseByValue} = counterSlice.actions;
    

5. Add reducer to the store

Now we have defined and exported the reducer so let's revisit the store to add reducer there.

import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../slice/counterSlice";
const store = configureStore({
    reducer: {
        counterReducer: counterReducer
    }
})

You can also add more than one slice reducers (an object of slice reducers)

configureStore({
    reducer: {
        counterReducer: counterReducer, 
	    userReducer: userReducer
    }
})

configureStore will automatically create the root reducer by passing this object to the Redux combineReducers utility.

6. Using actions in components

We'll use two hooks useSelector() and useDispatch() provided by react-redux. useSelector() hooks allows you to extract data from the Redux store state. useDispatch() hook is used to dispatch actions.

src\components\CounterWithRedux.js

import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { counterActions } from "../slice/counterSlice";

const CounterWithRedux = () => {
    const counter = useSelector((state) => state.counterReducer.value);
    const dispatch = useDispatch();
    const [incrementByValue, setIncrementByValue] = useState(0);
    const incrementHandler = () => {
        dispatch(counterActions.increment());
    }
    const decrementHandler =  () => {
        dispatch(counterActions.decrement());
    }
    const incrementByValueHandler = () => {
        dispatch(counterActions.increaseByValue(Number(incrementByValue)));
    }
    return (
        <div>
            <h2>Counter</h2>
            <div>
                <button className="btn btn-primary mx-2" onClick={incrementHandler}>+</button>            
                <span>{counter}</span>            
                <button className="btn btn-primary mx-2" onClick={decrementHandler}>-</button>
                <div className="mt-2">
                    <input value={incrementByValue} onChange={e => setIncrementByValue(e.target.value)}></input>
                    <button className="btn btn-primary mx-2" onClick={incrementByValueHandler}>Add Amount</button>
                </div>
            </div>
        </div>
    );
}

export default CounterWithRedux;

Some important points to note here-

  • We have used useSelector() to read data from store.
    const counter = useSelector((state) => state.counterReducer.value);
    

    What we are doing here is to go to the state produced by counterReducer.

    Remember that we have given 'counterReducer' identifier to our reducer which is also named counterReducer.

    import counterReducer from "../slice/counterSlice";
    const store = configureStore({
        reducer: {
            counterReducer: counterReducer
        }
    })
    

    From that state we are extracting data from 'value' property. Again, that's how we defined the state.

    initialState: {value: 0}
    
  • We can import generated action creators which is imported in CounterSlice.js file.
    import { counterActions } from "../slice/counterSlice";
    

    Now we can dispatch the required action by accessing it through counterActions.

    dispatch(counterActions.increment());
    dispatch(counterActions.decrement());
    
  • Note that Bootstrap is used here for styling.
Redux toolkit with React example

Source: https://redux-toolkit.js.org/tutorials/quick-start

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


You may also like

September 21, 2023

Java HashMap merge() With Examples

The Java HashMap merge() method is used to insert a new (key,value) pair into the HashMap or to modify value for an already existing key.

Syntax of Java HashMap merge() method

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

The parameters are-

  1. key- Key with which the resulting value has to be mapped.
  2. value- The non-null value which replaces the existing value associated with the key or inserts this new value.
  3. remappingFunction- It is an expression of type BiFunction functional interface used to recompute a value if present

merge method has the following scenarios-

  1. If the specified key is not already associated with a value associates it with the given non-null value and the (key, value) pair is inserted into the HashMap.
  2. If the specified key is associated with null value, associates it with the given non-null value.
  3. If the key already exists then replaces (or merges) the associated value with the results of the given remapping function.
  4. If the result of the given remapping function is null then removes the (key, value) pair from the HashMap.

Merge() Java examples

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

public class MapMergeDemo {

  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);
    // recomputing price
    products.merge("Laptop", 1200.0, (oldValue, newValue)-> oldValue- (oldValue*20/100));
    System.out.println("*** After Merge ***");
    System.out.println(products);
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=15.0, USB=10.45, RAM=60.5}
*** After Merge ***
{Laptop=960.0, Mouse=15.0, USB=10.45, RAM=60.5}

2. Inserting a new entry into the HashMap using merge method.

public class MapMergeDemo {
  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);
    // Adding new key
    products.merge("Adapter", 5.0, (oldValue, newValue)-> oldValue + newValue);
    System.out.println("*** After Merge ***");
    System.out.println(products);
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=15.0, USB=10.45, RAM=60.5}
*** After Merge ***
{Laptop=1200.0, Mouse=15.0, USB=10.45, Adapter=5.0, RAM=60.5}

3. If key exists but is associated with null value then value can be changed to a new value using merge() method . In the example HashMap has one key with associated value as null.

public class MapMergeDemo {
  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", null);
    System.out.println("*** Initial Values ***");
    System.out.println(products);
    // remappingFunction returns null
    products.merge("Mouse", 12.50, (oldValue, newValue)-> oldValue+newValue);
    System.out.println("*** After Merge ***");
    System.out.println(products);
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=null, USB=10.45, RAM=60.5}
*** After Merge ***
{Laptop=1200.0, Mouse=12.5, USB=10.45, RAM=60.5}

4. In this example we’ll see the scenario where remappingFunction of the merge() method 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 MapMergeDemo {

  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", 8.0);
    System.out.println("*** Initial Values ***");
    System.out.println(products);
    // remapping function returns null
    products.merge("Laptop", 1200.0, (oldValue, newValue)-> null);
    System.out.println("*** After Merge ***");
    System.out.println(products);
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=8.0, USB=10.45, RAM=60.5}
*** After Merge ***
{Mouse=8.0, USB=10.45, RAM=60.5}

5. In this example we’ll see the merging of old value and new value. Since the remapping function gets both old and new value as arguments so we can have logic to compute value using both old and new value. In the product HashMap if price of Laptop has to be increased by 20.

public class MapMergeDemo {

  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", null);
    System.out.println("*** Initial Values ***");
    System.out.println(products);
    products.merge("Laptop", 20.0, (oldValue, newValue)-> oldValue+newValue);
    System.out.println("*** After Merge ***");
    System.out.println(products);
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=null, USB=10.45, RAM=60.5}
*** After Merge ***
{Laptop=1220.0, Mouse=null, USB=10.45, RAM=60.5}

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

public class MapMergeDemo {

  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", 8.0);
    System.out.println("*** Initial Values ***");
    System.out.println(products);
    products.forEach((k,v) -> products.merge(k, v, (oldValue, newValue)-> oldValue+ (oldValue * 10/100)));
    System.out.println("*** After Merge ***");
    System.out.println(products);
  }
}
Output
*** Initial Values ***
{Laptop=1200.0, Mouse=8.0, USB=10.45, RAM=60.5}
*** After Merge ***
{Laptop=1320.0, Mouse=8.8, USB=11.495, RAM=66.55}

Here forEach is used to iterate the Map and then merge() method is used to increase value by 10%.

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


You may also like