Sunday, February 26, 2023

React Dynamic Form Using Formik's FieldArray Component

In this post you'll see how to create a React form with dynamic array field using Formik and Yup for object schema validation.

Many a times you need a form where you give user a functionality to add the same set of fields again and again which means giving an input or group of inputs as a dynamic array. For example, suppose you have a student form where you want to give a button to add qualification and whenever user clicks that button a new set of input fields for qualification should be added to the form.

Formik FieldArray

Dynamic React form using Formik's FieldArray

In Formik, which is a third party lightweight React form library, there is a <FieldArray> component that helps with common array/list manipulations. Using index of the array you can create input groups and do validations.

Formik's FieldArray example

In the example form we'll capture student details so the form fields are Student Name, Student Age and Qualification which is an array having two fields name and year. For the qualification field you want to provide the functionality that student should be able to add more than one qualification.

In this post we'll concentrate more on FieldArray, to get more details about Formik and Yup refer this post- React Form + Formik + Yup Validation Example

import { ErrorMessage, Field, FieldArray, Form, Formik, getIn } from "formik"
import * as Yup from 'yup';
import './form.css';
const StudentForm = () => {
  return (
    <Formik
      initialValues={{
        studentName: '',
        studentAge: '',
        qualification: [
          {
            name: '',
            year: ''
          }
        ]

      }}
      validationSchema={Yup.object({
        studentName: Yup.string()
            .max(20, 'Must be 20 characters or less')
            .required('Required'),
        studentAge: Yup.number()
            .min(18, 'Age must not be less than 18')
            .max(22, 'Age must not be greater than 22')
            .required('Required'),
        qualification: Yup.array().of(
            Yup.object().shape({
                name: Yup.string()
                    .required('Required'),
                year: Yup.number()
                    .required('Required'),
            })
        )
      })}
      onSubmit={(values, { setSubmitting }) => {
        setTimeout(() => {
            console.log(JSON.stringify(values, null, 2));
            setSubmitting(false);
        }, 400);
      }}

    >
    {({ errors, touched, values }) => (
      <Form>
          <h3>Student Form</h3>
          <div className="row">
              <div className="form-group col-sm-4 mb-2" >
                <label htmlFor="studentName" className="form-label">Student Name</label>
                <Field type="text" name="studentName" placeholder="Enter studentName"
                    className={'form-control' + (errors.studentName && touched.studentName ? ' is-invalid' : '')} />
                <ErrorMessage name="studentName" component="div" className="invalid-feedback" />
              </div>
              <div className="form-group col-sm-4 mb-2" >
                <label htmlFor="studentAge" className="form-label">Student Age</label>
                <Field type="text" name="studentAge" placeholder="Enter age"
                    className={'form-control' + (errors.studentAge && touched.studentAge ? ' is-invalid' : '')} />
                <ErrorMessage name="studentAge" component="div" className="invalid-feedback" />
              </div>
          </div>

          <FieldArray name="qualification">
            {({ remove, push }) => (

              <div>
                  <h4>Add qualifications</h4>
                  <button
                      type="button"
                      className="btn btn-secondary mb-2"
                      onClick={() => push({ name: '', year: '' })}
                  >
                      Add Qualification
                  </button>
                  {values.qualification.length > 0 &&
                    values.qualification.map((qual, index) => (

                    <div className="row" key={index}>
                      <div className="col-sm-4">
                        <label htmlFor={`qualification.${index}.name`} className="form-label">Name</label>
                        <Field
                            name={`qualification.${index}.name`}
                            placeholder="qualification"
                            type="text"
                            className={'form-control' + (getIn(errors, `qualification.${index}.name`) && getIn(touched, `qualification.${index}.name`) ? ' is-invalid' : '')}
                        />
                        <ErrorMessage
                            name={`qualification.${index}.name`}
                            component="div"
                            className="invalid-feedback"
                        />
                      </div>
                      <div className="col-sm-4">
                        <label htmlFor={`qualification.${index}.year`} className="form-label">Year</label>
                        <Field
                            name={`qualification.${index}.year`}
                            placeholder="year"
                            type="number"
                            className={'form-control' + (getIn(errors, `qualification.${index}.year`) && getIn(touched, `qualification.${index}.year`) ? ' is-invalid' : '')}
                        />
                        <ErrorMessage
                            name={`qualification.${index}.year`}
                            component="div"
                            className="invalid-feedback"
                        />
                      </div>
                      <div className="col-sm-1">
                        <label className="form-label">&nbsp;</label>
                        <button
                            type="button"
                            className="btn btn-danger btn-as-block"
                            onClick={() => remove(index)}
                        >
                            X
                        </button>
                      </div>
                  </div>
                ))}

              </div>
            )}
          </FieldArray>
          <button type="submit" className="btn btn-primary">Submit</button>
        </Form>
      )}

    </Formik>
  );
}

export default StudentForm;

There is also a small CSS code for aligning the delete button.

Form.css

.btn.btn-as-block {
  display: block;
}

Some important points to note here-

  1. In the example Bootstrap 5 is used for styling. You can import Bootstrap by adding following to the <head> section of the index.html file.
    <link rel="stylesheet" href=https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" />
    	
  2. Initial values for the form fields are as empty fields. You can see that qualification is defined as an array of objects with two properties- name and year.
    qualification: [
      {
        name: '',
        year: ''
      }
    ]
       
  3. In the validation Yup.array() function is used to provide validation for the fields in qualification array.
  4. The submission function (onSubmit) logs the form values.
  5. In the <Form> section some of the Bootstrap classes like form-group, form-label, form-control, is-invalid, invalid-feedback are used.
  6. If there is an error then apart from form-control, is-invalid class is also added.
  7. For adding qualification, a button "Add Qualification" is provided. On clicking it a new object with two fields- name, year is pushed into an array.
    <button
      type="button"
      className="btn btn-secondary mb-2"
      onClick={() => push({ name: '', year: '' })}>
        Add Qualification
    </button>
    
  8. To give unique name to each group of fields in the array index is used
    name={`qualification.${index}.year`}
    
  9. getIn, which is a utility function included in Formik is used to get errors for the specific index.
  10. With each array index another button to remove that index is also added.
    	<button
      type="button"
      className="btn btn-danger"
      onClick={() => remove(index)}>
        X
    </button>
    

With field validation error messages

React dynamic form validation

That's all for the topic React Dynamic Form Using Formik's FieldArray Component. If something is missing or you have something to share about the topic please write a comment.


You may also like

Friday, February 10, 2023

React Form + Formik + Yup Validation Example

In the post React Form Using Formik's useFormik() Hook we have seen how to create a form in React using Formik library and how to do validation. In that post we used useFormik() hook and did the validation ourselves. Formik provides integration with Yup for object schema validation.

Formik has a special configuration prop for Yup called validationSchema which will automatically transform Yup's validation errors messages into an object whose keys match values/initialValues/touched so that it is easy to map error message with the corresponding form field.

Installing Yup

you can install Yup from NPM or yarn

With npm

npm install yup -save

With yarn

yarn add yup

Using Formik component

To further reduce code and make it more readable Formik comes with components like <Formik />, <Form />, <Field />, and <ErrorMessage />. These formik components use React Context implicitly.

React form example with Formik and Yup

In this example we'll create a form with 5 fields- First Name, Last Name, Join Date, Email and Employment Type.

You can swap useFormik() hook with Formik component, with that you can pass initial values for the formFields, validation schema and a submission function.

<Formik 
  initialValues= {{
      firstName: '',
      lastName: '',
      joinDate: '',
      email: '',
      employmentType: 'permanent'
  }}
  validationSchema={Yup.object({
      firstName: Yup.string()
      .max(10, 'Must be 10 characters or less')
      .required('Required'),
      lastName: Yup.string()
      .max(15, 'Must be 15 characters or less')
      .required('Required'),
      joinDate:  Yup.date().max(new Date(), "Join date can't be greater than current date").required('Required'),
      email: Yup.string().email('Invalid email address').required('Required'),
  })}
  onSubmit={(values, { setSubmitting }) => {
      setTimeout(() => {
      console.log(JSON.stringify(values, null, 2));
      setSubmitting(false);
      }, 400);
  }}
>

By using Field component you don't need to pass event handlers- onChange, onBlur, value explicitly.

<Field type="text" name="firstName" />

Here is the full React form example using Formik, Field, Form, ErrorMessage components and Yup for validation.

import { ErrorMessage, Field, Form, Formik } from "formik";
import * as Yup from 'yup';
const EmployeeInfoForm = () => {
  return(
    <Formik 
      initialValues= {{
          firstName: '',
          lastName: '',
          joinDate: '',
          email: '',
          employmentType: 'permanent'
      }}
      validationSchema={Yup.object({
          firstName: Yup.string()
          .max(10, 'Must be 10 characters or less')
          .required('Required'),
          lastName: Yup.string()
          .max(15, 'Must be 15 characters or less')
          .required('Required'),
          joinDate:  Yup.date().max(new Date(), "Join date can't be greater than current date").required('Required'),
          email: Yup.string().email('Invalid email address').required('Required'),
      })}
      onSubmit={(values, { setSubmitting }) => {
          setTimeout(() => {
          console.log(JSON.stringify(values, null, 2));
          setSubmitting(false);
          }, 400);
      }}
    >
    {({ errors, touched }) => (
      <Form>

        <div className="form-group col-sm-4 mb-2" >
            <label htmlFor="firstName" className="form-label">First Name</label>
            <Field type="text" name="firstName" placeholder="Enter firstname" 
            className={'form-control' + (errors.firstName && touched.firstName ? ' is-invalid' : '')} />
            <ErrorMessage name="firstName" component="div" className="invalid-feedback" />       
        </div>
        <div className="form-group col-sm-4 mb-2" >
            <label htmlFor="lastName" className="form-label">Last Name</label>
            <Field type="text" name="lastName" className={'form-control'+ (errors.lastName && touched.lastName ? ' is-invalid' : '')}/>
            <ErrorMessage name="lastName" component="div" className="invalid-feedback"/>  
        </div>
        <div className="form-group col-sm-4 mb-2" >
            <label htmlFor="joinDate" className="form-label">Join Date</label>
            <Field type="date" name="joinDate" className={'form-control'+ (errors.joinDate && touched.joinDate ? ' is-invalid' : '')}/>
            <ErrorMessage name="joinDate" component="div" className="invalid-feedback"/>  
        </div>
        <div className="form-group col-sm-4 mb-2" >
            <label htmlFor="email" className="form-label">Email</label>
            <Field type="email" name="email" className={'form-control'+ (errors.email && touched.email ? ' is-invalid' : '')}/>
            <ErrorMessage name="email" component="div" className="invalid-feedback"/>  
        </div>
        <div className="form-group col-sm-4 mb-2" >
            <label htmlFor="employmentType" className="form-label">Employment Type:</label>
            <Field as="select" name="employmentType" className="form-select " >              
                <option value="permanent">Permanent</option>
                <option value="contract">Contract</option>
            </Field>
        </div>
          <div className="form-group col-sm-4 mb-2" >
              <button type="submit" className="btn btn-primary">Submit</button>
          </div>          
      </Form>
     )}
    </Formik>
  );
}

export default EmployeeInfoForm;

Some important points to note here-

  1. In the example Bootstrap 5 is used for styling. You can import Bootstrap by adding following to the <head> section of the index.html file.
    <link rel="stylesheet" href=https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" />
    
  2. Initial values for the form fields are as empty fields except for the employmentType which is a drop-down list where pre-selected option is given.
  3. Validation is done using Yup which is quite self-explanatory. For join date it should not go beyond the current date.
  4. The submission function (onSubmit) logs the form values.
  5. In the <Form> section some of the Bootstrap classes like form-group, form-label, form-control, is-invalid, invalid-feedback are used.
  6. If there is an error then apart from form-control, is-invalid class is also added.
  7. The <Field> component by default will render an <input> component. <Field> also accepts a few other props to let you render other elements like textarea, select.
    <Field name="message" as="textarea" />
    
    <Field name="employmentType" as="select"  />  
    

With Error Messages

React form with Formik

With All Form Values

React form Formik and Yup

That's all for the topic React Form + Formik + Yup Validation Example. If something is missing or you have something to share about the topic please write a comment.


You may also like

Wednesday, February 8, 2023

React Form Using Formik's useFormik() Hook

In the post React Form Creation and Validation Using React Hooks we have seen how to create a form using React and how to do validation. As you can notice the whole process of creating form in React is quite verbose if you do everything on your own.

You need to have a lot of repeated code for-

  1. Managing form fields states.
  2. Validation and when to show/not show error messages.
  3. Handling form submission

Formik, a third-party lightweight React form library addresses the above mentioned issues. Formik standardizes the creation of from fields and the form submission process.

Formik installation

You can install Formik with Yarn or NPM

With Yarn

yarn add formik

With npm

npm install formik -save

Formik React form example

In this example we'll create a form with 5 fields- First Name, Last Name, Join Date, Email and Employment Type. This example uses useFormik() which is a custom React hook.

Though using useFormik() hook is quite verbose and you can create a form using Formik in a more readable way using <Formik> component and using Yup for form validation. Check the post here- React Form + Formik + Yup Validation Example

Using useFormik() hook you can define the form fields, how to validate and form submission process at the same place.

const formik = useFormik({
  initialValues: {
    firstName: '',
    lastName: '',
    joinDate: '',
    email: '',
    employmentType: 'permanent'
  },
  validate,
  onSubmit: values => {
    alert(JSON.stringify(values, null, 2));
  },
});

As you can see form's initial values, a submission function (inSubmit) and a validation function (validate) is passed to the useFormik() hook.

Event handling

useFormik() hook returns form state and helper methods which can be used out of the box. Some of the helper methods you will use in your form are-

  • handleSubmit: A submission handler
  • handleChange: A change handler to pass to each <input>, <select>, or <textarea>
  • handleBlur: To keep track of which fields have been visited, stores this information in an object called touched which can store boolean values true or false
  • values: Our form’s current values

That's how you'll use handleSubmit

<form onSubmit={formik.handleSubmit}>
Using handleChange, handleBlur and value.
<input 
  type="text" 
  id="firstName" 
  name="firstName"
  onChange={formik.handleChange} 
  onBlur={formik.handleBlur}
  value={formik.values.firstName}>
</input>

With that Formik will take care of managing form fields state and event handling. You don't need to write custom event handlers for every single input.

Validation and error messages

Formik also keeps track of validation and error messages. You can specify a custom validation function and pass it as validate to the useFormik() hook. If an error exists, this custom validation function should produce an error object with properties matching the form values/initialValues.

You would generally show error once you come out of a form field. For that Formik has handleBlur() event handler to keep track of which fields have been visited.

That's how you'll write custom validate function.

const validate = values => {
    const errors = {};
    if (!values.firstName) {
        errors.firstName = 'Required';
    } else if (values.firstName.length > 10) {
        errors.firstName = 'Must be 10 characters or less';
    }
    // Validation for other fields

That's how you'll check if field visited and if field has error to display error message.

{formik.touched.firstName && formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}

Here is the full React form example created using useFormik() hook of Formik.

import { useFormik } from "formik"
import './form.css';
const validate = values => {
    const errors = {};
    if (!values.firstName) {
        errors.firstName = 'Required';
    } else if (values.firstName.length > 10) {
        errors.firstName = 'Must be 10 characters or less';
    }
    if (!values.lastName) {
        errors.lastName = 'Required';
    } else if (values.lastName.length > 15) {
        errors.lastName = 'Must be 15 characters or less';
    }
    if (!values.joinDate) {
        errors.joinDate = 'Required';
    }
    if (!values.email) {
        errors.email = 'Required';
    } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
        errors.email = 'Invalid email address';
    }
    return errors;
}
const EmployeeForm = () => {
    const formik = useFormik({
        initialValues: {
            firstName: '',
            lastName: '',
            joinDate: '',
            email: '',
            employmentType: 'permanent'
        },
        validate,
        onSubmit: values => {
            console.log(JSON.stringify(values, null, 2));
        },
    });
    return (
        <form onSubmit={formik.handleSubmit}>
            <div>
            <label htmlFor="firstName">First Name</label>
            <input type="text" id="firstName" name="firstName"
                onChange={formik.handleChange} onBlur={formik.handleBlur}
                value={formik.values.firstName}></input>
            {formik.touched.firstName && formik.errors.firstName ? <div className="error">{formik.errors.firstName}</div> : null}
            </div>
            <div>
            <label htmlFor="lastName">Last Name</label>
            <input type="text" id="lastName" name="lastName"
                onChange={formik.handleChange} onBlur={formik.handleBlur}
                value={formik.values.lastName}></input>
             {formik.touched.lastName && formik.errors.lastName ? <div className="error">{formik.errors.lastName}</div> : null}        
            </div>
            <div>
            <label htmlFor="joinDate">Join Date</label>
            <input type="date" id="joinDate" name="joinDate"
                onChange={formik.handleChange} onBlur={formik.handleBlur}
                value={formik.values.joinDate}></input>      
             {formik.touched.joinDate && formik.errors.joinDate ? <div className="error">{formik.errors.joinDate}</div> : null}      
            </div>
            <div>
            <label htmlFor="email">Email</label>
            <input type="email" id="email" name="email"
                onChange={formik.handleChange} onBlur={formik.handleBlur}
                value={formik.values.email}></input>
            {formik.touched.email && formik.errors.email ? <div className="error">{formik.errors.email}</div> : null}    
            </div>
            <div>
            <label htmlFor="employmentType">Employment Type:</label>
                <select id="employmentType" name="employmentType" 
                  value={formik.values.employmentType} onChange={formik.handleChange} 
                  onBlur={formik.onBlur}>
                    <option value="permanent">Permanent</option>
                    <option value="contract">Contract</option>
                </select>
            </div>
            <button type="submit" disabled={!(formik.dirty && formik.isValid)}>Submit</button>
        </form>
    )
}
export default EmployeeForm;

To keep focus on the form styling is not used, only styling is for error message.

form.css

.error {
  color: red;
}

Some important points to note here-

  1. In the useFormik() hook, initialValues for the form fields are passed, all but one as empty fields, for the employmentType which is a drop-down list pre-selected option is there.
  2. A custom validation function is written to validate the form fields and create error messages. Reference for that function is also passed to the hook.
  3. onSubmit function just logs the form values.
  4. With form fields the same event handler functions (handleChange, handleBlur) are used, which is one of the benefit of using Formik library.
  5. Form values are passed to the validate function and the validation based on the requirement is done for the fields there. Error messages for the fields are also created.
  6. Formik keeps track of the visited fields and based on whether the field is touched or not and if it fails validation, error message for the field is displayed.

That's all for the topic React Form Using Formik's useFormik() Hook. If something is missing or you have something to share about the topic please write a comment.


You may also like

Saturday, January 28, 2023

Java Generics - Type Erasure

Using Java generics you can write generic programs and it also provide tighter type checks at compile time but these generics type remain only at source code level. When the source code is compiled all the generic type parameters are erased and this process is called type erasure in Java Generics.

How does Type erasure work

Type erasure in Java works as follows-

  1. Replace all type parameters in generic types with their bound type, if no explicit bound type is specified then replace generic type parameter with Object. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods with all the generic parameters replaced with actual types.
  2. Insert type casts if necessary to preserve type safety.
  3. Generate bridge methods to preserve polymorphism in extended generic types.

Type erasure in Generic class

Consider the following generic class with a generic type parameter T.

public class GenericClass<T> {
  T obj;
  GenericClass(T obj){
    this.obj = obj;
  }
  public T getObj() {
    return obj;
  } 
}

Because the type parameter T is unbounded, the Java compiler replaces it with Object and after compilation class looks like-

public class GenericClass {
  Object obj;
  GenericClass(Object obj){
    this.obj = obj;
  }
  public Object getObj() {
    return obj;
  } 
}

Consider another generic class with a bounded type parameter.

public class GenericClass<T extends String> {
  T obj;
  GenericClass(T obj){
    this.obj = obj;
  }
  public T getObj() {
    return obj;
  } 
}

Because the type parameter T is bounded, the Java compiler replaces it with the bound class String and after compilation class looks like-

public class GenericClass {
  String obj;
  GenericClass(String obj){
    this.obj = obj;
  }
  public String getObj() {
    return obj;
  } 
}

Type erasure in Generic method

The Java compiler also erases type parameters in generic method arguments. Consider the following generic method which counts the number of occurrences of passed element in the passed array.

public static <T> int count(T[] numberArray, T elem) {
  int cnt = 0;
  for (T e : numberArray){
    if (e.equals(elem))
      ++cnt;
  }
  return cnt;
}

Because T is unbounded, the Java compiler replaces it with Object and the compiled method looks like-

public static int count(Object[] numberArray, Object elem) {
  int cnt = 0;
  for (Object e : numberArray){
    if (e.equals(elem))
      ++cnt;
  }
  return cnt;
}

Type erasure and bridge methods

Sometimes, as part of the type erasure process compiler creates a synthetic method, called a bridge method. Consider the following classes to see an example of bridge method in Java.

public class GenClass<T> {
  T obj;
  public GenClass(T obj) { 
    this.obj = obj; 
  }
  public void setObj(T obj) {
    this.obj = obj;
  }  
}

This GenClass is then extended by another class as given below-

public class MyClass extends GenClass {
  public MyClass(Integer data) { 
    super(data); 
  } 
  public void setObj(Integer data) {
    System.out.println("MyClass.setData");
    super.setObj(data);
  } 
}

The intention here is to override the parent class setObj() method in the subclass. After type erasure, the GenClass and MyClass classes become-

public class GenClass {
  Object obj;
  public GenClass(Object obj) { 
    this.obj = obj; 
  }
  public void setObj(Object obj) {
    this.obj = obj;
  }  
}
public class MyClass extends GenClass {
  public MyClass(Integer data) { 
    super(data); 
  } 
  public void setObj(Integer data) {
    System.out.println("MyClass.setData");
    super.setObj(data);
  } 
}

After type erasure, the method signatures do not match. The GenClass method becomes setObj(Object obj) and the MyClass method becomes setObj(Integer data). Therefore, the GenClass setObj method does not override the MyClass setObj method.

To solve this problem and preserve the polymorphism of generic types after type erasure, Java compiler generates a bridge method to ensure that subtyping works as expected. For the MyClass class, the compiler generates the following bridge method for setObj().

public class MyClass extends GenClass {
  public MyClass(Integer data) { 
    super(data); 
  } 
  // Bridge method generated by the compiler
  public void setObj(Object data) {
    setObj((Integer) data);
  }
  public void setObj(Integer data) {
    System.out.println("MyClass.setData");
    super.setObj(data);
  } 
}

As you can see the bridge method has the same method signature as the GenClass’ setObj() method and it delegates to the original setObj() method.

That's all for the topic Java Generics - Type Erasure. If something is missing or you have something to share about the topic please write a comment.


You may also like

Heap Sort Java Program

This tutorial shows how to write Heap sort program in Java which is an in-place sorting algorithm. Heap sort uses heap data structure for sorting the elements so the obvious question is what is heap?

Heap data structure

A heap is a binary tree so each node can have maximum two children and it has following properties-

  1. It is a complete binary tree which means reading from left to right it is completely filled in (all the nodes have 2 children) except the last row which need not be full.
  2. Each node in the heap satisfies the condition that each node is greater than or equal to its child nodes in case of Max heap. Node is less than or equal to its child nodes in case of Min heap.
Heap data structure

Heap sort algorithm

Steps for writing the Heap Sort Java program are as follows-

  1. Create a max heap from input array. Using max heap sorting will be done in ascending order. For descending order you can use min heap. Heap data structure is also represented using array. This process of creating heap from the input array is called heapify.
  2. Once the heap is created its root node is the maximum element. Swap the root element with the last element of the array.
  3. This swapping disturbs the heap so structure has to be heapified again using the array. This time last element is excluded (array length decreased by one) as it is already at its final place.
  4. Repeat step 2 and 3 until sorting is complete.

How to create heap from array

Creating heap from an array is an important part of heap sort so understanding it is important.

Array is considered as a complete binary tree with each element considered as a node. With in an array for each node you can get its parent node, left child node and right child node using the following equations-

For a node at index i in the array-

  • Parent node is– (i-1)/2
  • Left child node is- 2*i + 1
  • Right child node is- 2*i+2

To create a heap you'll have to start from the nodes at the bottom and move upwards comparing if child node is greater than the parent and swapping node values if that is true. Since last level has leaf nodes (nodes with no children) so this comparison has to be started from one level above.

For an array of length n, last node will be at index (n-1) thus the index of its parent node should be (n-1)/2 using the equation. Heapifying the array starts from this parent node, in each iteration compare the parent node with left child and right child and swap the nodes if child is greater than the parent.

For example if input array is [5, 12, 3, 16, 8, 10] then the complete binary tree for this array can be visually represented as-

Binary tree

Since last index is 5 thus the parent node should be at index (5-1)/2 = 2. Process of creating a heap starts from that index 2. Compare node at index 2 with its child nodes and swap if any of the child is greater than the parent node. In our tree 10 > 3 so these values are swapped. When index is 1, node at index 1 is compared with its child nodes and values swapped if required.

heap sort

In next iteration comparison and swapping is done for index 0.

Heap Sort Java

Heap Sort Java program

public class HeapSort {

  public static void main(String[] args) {
    int[] arr = {5, 12, 3, 16, 8, 10};	
    System.out.println("Original array- " + Arrays.toString(arr));
    HeapSort hs = new HeapSort();
    hs.heapSort(arr);
    System.out.println("Sorted array after heap sort- " + Arrays.toString(arr));
  }
	
  private void heapSort(int[] arr){
    int arrLength = arr.length;
    // create heap from array start from index (n-1)/2
    for(int i = (arrLength-1)/2; i >= 0; i--){
      heapify(arr, arrLength, i);
    }
    System.out.println("heapified array- " + Arrays.toString(arr));
    // Heap Sort 
    for(int i = arrLength-1; i >= 0; i--){
      // Swap root and last nodes 
      swap(arr, i, 0);
      // Reconstruct heap again 
      heapify(arr, i, 0);
    }
  }
    
  private void heapify(int[] numArr, int index, int i){
    // Getting parent and children indexes
    int root = i;
    int leftChild = 2*i + 1;
    int righChild = 2*i + 2;
    //compare left child value
    if(leftChild < index && numArr[leftChild] > numArr[root])
      root = leftChild;
    //comparing right child value
    if(righChild < index && numArr[righChild] > numArr[root])
      root = righChild;
      // swap values if required and call method recursively for next level
      if(root != i){
        swap(numArr, root, i);
        heapify(numArr, index, root);
      }
    }
    
    private void swap(int[] numArr, int index, int li){
      int temp = numArr[li];
      numArr[li] = numArr[index];
      numArr[index] = temp;
    }
}

Heap sort time and space complexity

Time required to do any common tree operation is O(logn). For Heap sort creation of heap is done for n elements thus the time complexity of Heap sort is O(n*logn). This time complexity remains the same however the data is distributed. That’s where Heap sort scores over Quick sort which is another O(n*logn) sorting algorithm. In worst case Quick sort may become O(n2) but Heap sort is always O(n*logn).

Since same array is used for arranging the elements in order so no extra space requirement is there. Thus the space complexity of Heap sort is O(1).

That's all for the topic Heap Sort Java Program. If something is missing or you have something to share about the topic please write a comment.


You may also like

Thursday, January 26, 2023

Java TemporalAdjusters Class With Examples

The java.time.temporal.TemporalAdjusters class is part of new date and time API added in Java 8 which provides common and useful TemporalAdjusters. TemporalAdjusters class in Java has many static methods for modifying temporal objects i.e. methods for adjustments of date and time.

You have to understand two interfaces Temporal and TemporalAdjuster to understand the whole concept of temporal objects.

java.time.temporal.Temporal interface

Temporal is a framework-level interface defining read-write access to a temporal object, such as a date, time, offset or some combination of these.

This is the base interface type for date, time and offset objects that are complete enough to be manipulated using plus and minus thus it provides access to date/time/offset information.

Some of the classes in new date and time API that implements Temporal interface are given below-

  • Instant
  • LocalDate
  • LocalDateTime
  • LocalTime
  • OffsetDateTime
  • OffsetTime
  • ZonedDateTime

So objects of these classes are of type Temporal and static methods of TemporalAdjusters class can modify these temporal objects.

java.time.temporal.TemporalAdjuster interface

TemporalAdjuster is a functional interface providing strategy for adjusting a temporal object. This interface has a single abstract method adjustInto() which adjusts the specified temporal object.

For example-

temporal = thisAdjuster.adjustInto(temporal);

But the recommended way is to use temporal = temporal.with(thisAdjuster); method rather than directly using the adjustInto() method.

java.time.temporal.TemporalAdjusters class

TemporalAdjusters class has many convenient methods that return a TemporalAdjuster. Some of the methods are listed below-

  • TemporalAdjuster dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)- Returns the day-of-week in month adjuster, which returns a new date with the ordinal day-of-week based on the month.
  • TemporalAdjuster firstDayOfMonth()- Returns the "first day of month" adjuster, which returns a new date set to the first day of the current month.
  • TemporalAdjuster firstDayOfNextMonth()- Returns the "first day of next month" adjuster, which returns a new date set to the first day of the next month.
  • TemporalAdjuster firstDayOfYear()- Returns the "first day of year" adjuster, which returns a new date set to the first day of the current year.
  • TemporalAdjuster lastDayOfMonth()- Returns the "last day of month" adjuster, which returns a new date set to the last day of the current month.
  • TemporalAdjuster lastDayOfYear()- Returns the "last day of year" adjuster, which returns a new date set to the last day of the current year.

Java TemporalAdjusters Examples

1. Finding the first or last day of the month for a LocalDateTime object.

LocalDateTime ldt = LocalDateTime.now();
System.out.println("Current date time- " + ldt);
System.out.println("First day of the month- " + ldt.with(TemporalAdjusters.firstDayOfMonth()));
System.out.println("Last day of the month - " + ldt.with(TemporalAdjusters.lastDayOfMonth()));
Output
Current date time- 2019-11-20T10:39:26.583287900
First day of the month- 2019-11-01T10:39:26.583287900
Last day of the month – 2019-11-30T10:39:26.583287900

2. Finding the day of week in the month for a LocalDate object. In the example code first Sunday of the given month and the previous Sunday is calculated.

LocalDate ld = LocalDate.now();
System.out.println("Current Date - " + ld);
System.out.println("First Sunday of the month - " + ld.with(TemporalAdjusters.dayOfWeekInMonth(1, DayOfWeek.SUNDAY)));
System.out.println("Previous Sunday - " + ld.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY)));
Output
Current Date - 2019-11-20
First Sunday of the month - 2019-11-03
Previous Sunday – 2019-11-17

Custom TemporalAdjuster examples

You can implement your own TemporalAdjuster to cater to specific requirement. Suppose you want to get the last working day of the month.

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

public class WorkingDayAdjuster implements TemporalAdjuster {
  @Override
  public Temporal adjustInto(Temporal temporal) {
    LocalDateTime ldt = LocalDateTime.from(temporal);
    ldt = ldt.with(TemporalAdjusters.lastDayOfMonth());
    if(ldt.getDayOfWeek() == DayOfWeek.SATURDAY || ldt.getDayOfWeek() == DayOfWeek.SUNDAY) {
      ldt = ldt.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
    }
    return temporal.with(ldt);
  }
}
public class WorkingDay {
  public static void main(String[] args) {
    LocalDateTime ldt = LocalDateTime.now();
    System.out.println("Current Date - " + ldt);
    System.out.println("Last working day of the month - " + ldt.with(new WorkingDayAdjuster()));
  }
}
Output
Current Date - 2019-11-20T11:10:48.365786300
Last working day of the month - 2019-11-29T11:10:48.365786300

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


You may also like

Java Reflection – Class Fields

Using Java Reflection you can get information about the class fields and get and set field values at run time. In Java Reflection API there is a class java.lang.reflect.Field that has methods for accessing field's type, field’s modifier and setting and getting values of a field.

Getting Field instance

First thing is to get the instance of Field class for that you will have to use methods of the java.lang.Class as that class is the entry point for all reflection operations.

There are 4 methods for getting field instance-

  1. getField(String name)- Returns a Field object representing the public member field of the class or interface.
  2. getFields()- Returns an array containing Field objects reflecting all the accessible public fields of the class or interface.
  3. getDeclaredField(String name)- Returns a Field object that reflects the specified declared field (even private) of the class or interface represented by this Class object.
  4. getDeclaredFields()- Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields.

Getting information about class fields – Java example

This example shows how to get information like type, modifier of individual/all fields of a class. Methods of the Field class used are-

  • getType() method of the Field class returns the declared type for the field.
  • getModifiers() method of the field class returns the modifiers for the field as an integer.
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Set;

public class FieldReflectionDemo {
  public String str = "Reflection";
  private int i;
  public boolean flag = false;
  public Set<String> citySet;
    
  public static void main(String[] args) {
    try {
      FieldReflectionDemo obj = new FieldReflectionDemo();
      Class<?> c = obj.getClass();
      // get specific field
      Field f = c.getField("str");
      // getting field type
      Class<?> type = f.getType();
      // getting field modifiers
      int mod = f.getModifiers();
      System.out.println("Field name - " + f.getName()); 
      System.out.println("Field type - " + type.getName());
      System.out.println("Field modifiers - " + Modifier.toString(mod));
      System.out.println("--- Getting all fields ---");
      Field[] fields = c.getDeclaredFields();
      for(Field field : fields) {
        System.out.println("Field name - " + field.getName()); 
        System.out.println("Field type - " + field.getType());
        System.out.println("Field modifiers - " + Modifier.toString(field.getModifiers()));
      }        
    } catch (NoSuchFieldException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Field name - str
Field type - java.lang.String
Field modifiers - public
--- Getting all fields ---
Field name - str
Field type - class java.lang.String
Field modifiers - public
Field name - i
Field type - int
Field modifiers - private
Field name - flag
Field type - boolean
Field modifiers - public
Field name - citySet
Field type - interface java.util.Set
Field modifiers - public

Getting and setting values

For getting value there is get(Object obj) method which returns the value of the field represented by this Field, on the specified object.

For Setting value there is set(Object obj, Object value) method which sets the field represented by this Field object on the specified object argument to the specified new value.

import java.lang.reflect.Field;
import java.util.Set;

public class FieldReflectionDemo {
  public String str = "Reflection";
  private int i;
  public boolean flag = false;
  public Set<String> citySet;
    
  public static void main(String[] args) {
    try {
      FieldReflectionDemo obj = new FieldReflectionDemo();
      Class<?> c = obj.getClass();
      // get specific field
      Field f = c.getField("str");
      // show value - get method
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
      // set new value
      f.set(obj, "New Value");
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));        
    } catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
Field name- str Value- Reflection
Field name- str Value- New Value

Getting and setting value of a private field

You can even set value of a private field using Reflection. For that you need to set the accessible as true using setAccesssible() method.

In the example we have a class Access with one private int field i. In FieldReflectionDemo class we’ll access this field using reflection and set a value to it. If you don’t set the accessible flag using setAccesssible() method it will throw IllegalAccessException as shown below.

class Access{
  private int i;
}

public class FieldReflectionDemo {
  public String str = "Reflection";
  public boolean flag = false;
  public Set<String> citySet;
    
  public static void main(String[] args) {
    try {
      Access obj = new Access();
      Class<?> c = obj.getClass();
      // get specific field
      Field f = c.getDeclaredField("i");
      // show value - get method
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
      // set new value
      f.set(obj, 7);
      System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));       
    } catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
java.lang.IllegalAccessException: class com.knpcode.programs.FieldReflectionDemo cannot access a member of class com.knpcode.programs.Access with modifiers "private"

Run again after making this change and you will be able to access even the private fields.

Field f = c.getDeclaredField("i");
f.setAccessible(true);
Output
Field name- i Value- 0
Field name- i Value- 7

Reference: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/reflect/Field.html

That's all for the topic Java Reflection – Class Fields. If something is missing or you have something to share about the topic please write a comment.


You may also like