Google

Jul 3, 2014

Fizz Buzz Java coding example

Q. Write a program that prints numbers from 1 to 30, but for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz"?
A. This is a very basic coding question, but still some struggle or take too long (more than 5 minutes) to solve this coding problem. Be prepared for the interviewer to quiz you on different approaches to solve this coding problem. Be prepared to discuss DRY principle and optimization techniques to compare only once, etc.

There could be other variations. Arbitrary sets of number/word combinations (3 = Foo, 5=Bar, 7=Bazz, 11=Banana), etc.

One of the Java operators is "modulus", the name most programmers use for the remainder operator. It uses the symbol "%". Basically, "A % B" represents the remainder left over after dividing A by B. You use this operator to determine if a number is odd (i%2 != 0) or even (i%2 == 0).

Approach 1:

public class FizzBuzz {
 
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder(500);
        for (int i = 1; i <= 30; i++) {
            if (i % 15 == 0) {
               builder.append("FizzBuzz");
            }
            else if (i % 3 == 0) {
               builder.append("Fizz");
            }
            else if (i % 5 == 0){
              builder.append("Buzz");
            }
            else {
              builder.append(i);
            }
            builder.append('\n');
        }
        
        System.out.println(builder);
    }
}

Approach 2: Don't Repeat Yourself (DRY) approach with use of "Fizz" and "Buzz" not repeated. The boolean flag "processed" is used to determine if a number was multiples of 3, 5 or both.

public class FizzBuzzDry {
 
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder(500);
        for (int i = 1; i <= 30; i++) {
            boolean processed = false; 
            if (i % 3 == 0) {
               builder.append("Fizz");
               processed = true;
            }
            if (i % 5 == 0) {
               builder.append("Buzz");
               processed = true;
            }
   
            if (!processed) builder.append(i);
            builder.append('\n');
       }
        
       System.out.println(builder);
    }
}

Approach 3: Same as DRY approach shown above, but instead of using a boolean flag to determine if multiples of 3,5, or both, the length of the builder is compared before and after to see if already processed

public class FizzBuzzDry2 {

 public static void main(String[] args) {
  StringBuilder builder = new StringBuilder(500);
  for (int i = 1; i <= 30; i++) {
    int length = builder.length();
    if (i % 3 == 0)
      builder.append("Fizz");
    if (i % 5 == 0)
      builder.append("Buzz");
    if (length == builder.length())
      builder.append(i);
    
    builder.append('\n');
  }

  System.out.println(builder);
 }
}


I am sure there are many more approaches possible. For example, using a conditional operator, etc.

          builder.append(
          i % 15 == 0
                 ? "FizzBuzz"
                 : (i % 3 == 0
                     ? "Fizz"
                     : (i % 5 == 0
                         ? "Buzz"
                         : i)));
          builder.append("\n");

Labels:

Jun 29, 2014

Can you write an abstract Java comparator that will work with multiple fields to sort on?

Comparators are used in Java to custom sort objects. You need good coding skills to write abstract classes.

Q. Can you write an abstract Comparator class that will allow more specific comparator classes like EmployeeComparator to sort an object like Employee shown below?


package test;

public class Employee {
 
 private String firstName;
 private String surname;
 private int age;
 
 public Employee(String firstName, String surname, int age, Gender gender) {
  super();
  this.firstName = firstName;
  this.surname = surname;
  this.age = age;
 }
 protected String getFirstName() {
  return firstName;
 }
 protected void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 protected String getSurname() {
  return surname;
 }
 protected void setSurname(String surname) {
  this.surname = surname;
 }
 protected int getAge() {
  return age;
 }
 protected void setAge(int age) {
  this.age = age;
 }
 
 @Override
 public String toString() {
  return "Employee [firstName=" + firstName + ", surname=" + surname + ", age=" + age + "]\n";
 }
 
}


A. Pay attention to the Generics, inner class, and access control modifiers. It may look easy, but try writing it yourself.

Step 1:  Create the "AbstractGenericComparator" that can be extended by more specific comparator classes to extend.

 package test;

import java.util.Comparator;

/**
 * class is abstract, hence should have at least 1 abstract method. 
 * T is the type of object to compare 
 * S is the type of SortBy that defines --> Field and order for sorting
 */
public abstract class AbstractGenericComparator<T, S> implements Comparator<T> {

 // array of multiple sort by fields
 private SortBy<S>[] sortBy;
 
 @SafeVarargs
 //takes var args 1 or more SortBy fields
 public AbstractGenericComparator(SortBy<S>... sortBy) {
  //fail fast & precondition check
  if (sortBy.length == 0) {
   throw new IllegalArgumentException("At least one SortByr must be supplied!");
  }
  this.sortBy = sortBy;
 }

 @Override
 public int compare(T o1, T o2) {
  int result = 0;
  //sort by 1 or more fields.
  for (int index = 0; index < this.sortBy.length; index++) {
            result = compare(this.sortBy[index], o1, o2);
            if (result != 0) {
                return result;
            }
        }
        return result;
 }
 
 protected SortBy<S>[] getSortBy() {
  return sortBy;
 }

 protected abstract int compare(SortBy<S> sortBy, T o1, T o2);

 // static inner class
 public static class SortBy<S> {
 
  private S field;
  private boolean isAscending = true;
  
  protected S getField() {
   return field;
  }
  protected void setField(S field) {
   this.field = field;
  }
  protected boolean isAscending() {
   return isAscending;
  }
  protected void setAscending(boolean isAscending) {
   this.isAscending = isAscending;
  }
 }

}

Step 2: Create the EmployeeComparator that extends AbstractGenericComparator.

package test;

public class EmployeeComparator<T,S> extends
  AbstractGenericComparator<Employee, String> {

 @SafeVarargs
 public EmployeeComparator(SortBy<String>... sortBy) {
  super(sortBy);
 }
 
 @Override
 /**
  * simplified. Not handling null, etc at this point
  * Assuming that firstname, surname, and age are mandatory fields.
  */
 protected int compare(SortBy<String> sortBy, Employee o1, Employee o2) {

  Employee e1 = (Employee) o1;
  Employee e2 = (Employee) o2;

  //Java 7 switch statement supports String
  switch (sortBy.getField()) {
  case "firstName":
   if (sortBy.isAscending()) {
    return e1.getFirstName().compareTo(e2.getFirstName());
   } else {
    return -e1.getFirstName().compareTo(e2.getFirstName());
   }
  case "surname":
   if (sortBy.isAscending()) {
    return e1.getSurname().compareTo(e2.getSurname());
   } else {
    return -e1.getSurname().compareTo(e2.getSurname());
   }
   
  case "age":
   if (sortBy.isAscending()) {
    return new Integer(e1.getAge()).compareTo(e2.getAge());
   } else {
    return  -new Integer(e1.getAge()).compareTo(e2.getAge());
   }
  default:
   throw new UnsupportedOperationException("Reached unsupported comparison");
  }

 }
}


Step 3: Write a test class with main method.

package test;



import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import test.AbstractGenericComparator.SortBy;

public class ComparatorTest {

 public static void main(String[] args) {
  
  //create Employee objects
  Employee emp1 = new Employee("Paul", "Smith", 15, Employee.Gender.Male);
  Employee emp2 = new Employee("Emma", "Smith", 28, Employee.Gender.Female);
  Employee emp3 = new Employee("Emma", "Smith", 18, Employee.Gender.Female);
  Employee emp4 = new Employee("John", "Anders", 17, Employee.Gender.Male);

  List<Employee> employees = new ArrayList<Employee>();
  employees.add(emp1);
  employees.add(emp2);
  employees.add(emp3);
  employees.add(emp4);

  //Create SortBY objects
  SortBy<String> sortByFirstName = new SortBy<String>();
  sortByFirstName.setField("firstName");

  SortBy<String> sortBySurname = new SortBy<String>();
  sortBySurname.setField("surname");

  SortBy<String> sortByAge = new SortBy<String>();
  sortByAge.setField("age");

  System.out.println("Before sorting");
  System.out.println(employees);
  
  //Create an EmployeeComparator
  EmployeeComparator<Employee, String> sorter = 
   new EmployeeComparator<Employee, String>(sortByFirstName,sortBySurname, sortByAge);
    
  Collections.sort(employees, sorter);
        
  System.out.println("\nafter sorting by firstName, surname, and age");
  System.out.println(employees);
  
  //Create another EmployeeComparator
  EmployeeComparator<Employee, String> sorter2 = 
    new EmployeeComparator<Employee, String>(sortByAge,sortByFirstName,sortBySurname);

  
  Collections.sort(employees, sorter2);
  
  System.out.println("\nafter sorting by age,surname, and firstname ");
  System.out.println(employees);
  
 }
}

Output:

Before sorting
[Employee [firstName=Paul, surname=Smith, age=15]
, Employee [firstName=Emma, surname=Smith, age=28]
, Employee [firstName=Emma, surname=Smith, age=18]
, Employee [firstName=John, surname=Anders, age=17]
]

after sorting by firstName, surname, and age
[Employee [firstName=Emma, surname=Smith, age=18]
, Employee [firstName=Emma, surname=Smith, age=28]
, Employee [firstName=John, surname=Anders, age=17]
, Employee [firstName=Paul, surname=Smith, age=15]
]

after sorting by age,surname, and firstname 
[Employee [firstName=Paul, surname=Smith, age=15]
, Employee [firstName=John, surname=Anders, age=17]
, Employee [firstName=Emma, surname=Smith, age=18]
, Employee [firstName=Emma, surname=Smith, age=28]
]


Labels: ,