Recursion in Java

A Recursion is when the method calls itself to solve a problem. The recursive solution is constructed with a base case and a recursive case. In every recursive solution, we need to have these two components. If we miss base case in our recursive solution, the method will run in never ending loop and will throw StackOverFlowError.

Base Case

A non-recursive method that terminates the recursive path. This should run first in a method to check to terminate the recursive path.

Recursive Case

A recursive method that calls itself one or multiple times to solve a problem.

The best example of recursion is to compute the factorial of a number. In mathematics, a factorial is what you get when you multiply a number by all of the integers below it. The factorial of 6 is equal to 6 * 5 * 4 * 3 * 2 * 1 = 720. We can write a recursive function for factorial as follows in java:

public static int factorial(int n) {
	if (n <= 1) {
		return 1;
	} else {
		return n * factorial(n - 1);
	}
}

If we trace the function call of above recursive function, we can see as follows:

factorial(6)
	factorial(5)
		factorial(4)
			factorial(3)
				factorial(2)
					factorial(1)
					return 1
				return 2*1 = 2
			return 3*2 = 6
		return 4*6 = 24
	return 5*24 = 120
return 6*120 = 720

In this example, you see that 1 is the base case, and any integer value greater than 1 triggers the recursive case.

One challenge in implementing a recursive solution is always to make sure that the recursive process arrives at a base case. For example, if the base is never reached, the solution will continue infinitely and the program will hang. In java, this will result in a StackOverFlowError anytime the application recurses too deeply.

Following famous algorithms are using recursive strategy to solve a problem

  1. Euclid’s algorithm
  2. Towers of Hanoi
  3. Brownian bridge

Properties File Formats for Java

The most common syntax is where a property file contains key/value pairs in the following format. If you define the log4j.properties file, you might define following way which is the default way of doing it.

#This is a stub log4.properties file used by the bootstrap process

log4j.rootCategory=info, stdout, rf

#---------------------
#Log to Console
#---------------------
#Log messages to the console for priority INFO, WARN, ERROR, and FATAL
#To Log debug or trace, set log4j.rootCategory to DEBUG or TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#
#DEFAULT - log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %n
#Pattern 1 - full class name - log4j.appender.stdout.layout.ConversionPattern=%d %p [%t:%c] - %n
#Pattern 2 - no class name
#
log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%c{2}:%t] - %n
log4j.appender.stdout.Threshold=info


#---------------------
#Log to Rolling File
#---------------------
#Log messages to the log file (backed up each day) for priority INFO, WARN, ERROR, and FATAL
#To Log debug or trace, set log4j.rootCategory to DEBUG or TRACE
log4j.appender.rf=org.apache.log4j.DailyRollingFileAppender
log4j.appender.rf.File=log/app-bootstrap.log
log4j.appender.rf.DatePattern='.'yyyy-MM-dd
log4j.appender.rf.Append=true
log4j.appender.rf.layout=org.apache.log4j.PatternLayout
log4j.appender.rf.layout.ConversionPattern=%d %-5p [%c{2}:%t] - %n
log4j.appender.rf.Threshold=debug

There is more to it than that. There are actually two other format that you can use to express these pairs. Even if you never use them in your job, it is better to know in case you might encounter in code.

name:David
name David

You might wonder how to express some other ideas in a property file. The common ones are as follows:

  1. If a line begins with # or !, it is a comment. I use # syntax on above property file defination for comment.
  2. Spaces before or after the separator character are ignored.
  3. Spaces at the beginning of a line are ignored.
  4. Spaces at the end of a line are not ignored.
  5. End a line with a backlash if you want to break the line for readability.
  6. You can use normal Java escape characters like \t and \n.

If we put these concepts together, we can write the following:

# one comment
! second comment
key =    value
string = value \tafter tab
long = lkajdfljasdlj\
nandfsdlkjfdlj

Printing our these two properties in a program gives us theses:

value
value [tab] after tab
lkajdfljasdljnandfsdlkjfdlj

 
It is always good to know how many ways the properties file can be written. There are various ways to read these kinds of property files as well. One of the way is to use FileInputStream to load all the properties of a file to Properties object as follows:

public static void main(String[] args) {
	Properties prop = new Properties();
	InputStream input = null;
	try {
		input = new FileInputStream("config.properties");

		// load a properties file
		prop.load(input);

		// get the property value and print it out
		System.out.println(prop.getProperty("database"));
		System.out.println(prop.getProperty("dbuser"));
		System.out.println(prop.getProperty("dbpassword"));
	} catch (IOException ex) {
		ex.printStackTrace();
	} finally {
		if (input != null) {
			try {
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
  }

Another way is to use ResourceBundle. ResourceBundle.getBundle() takes property file name and the Locale object to distinguish which property file to load. It always loads file from resource folder of a project.


// ResourceBundle class will use SystemMessages.properties file
ResourceBundle resourceBundle = ResourceBundle.getBundle(
"SystemMessages", Locale.getDefault());
logger.info(resourceBundle.getString("first_name") + ": David");
logger.info(resourceBundle.getString("last_name") + ": Dang");

// ResourceBundle class will use SystemMessages_es.properties file
resourceBundle = ResourceBundle.getBundle("SystemMessages",
Locale.forLanguageTag("es"));
logger.info(resourceBundle.getString("first_name") + ": David");
logger.info(resourceBundle.getString("last_name") + ": Dang");

// ResourceBundle class will use SystemMessages_fr.properties file
resourceBundle = ResourceBundle.getBundle("SystemMessages",
Locale.FRANCE);
logger.info(resourceBundle.getString("first_name") + ": David");
logger.info(resourceBundle.getString("last_name") + ": Dang");

If you want to learn more about ResourceBundle, please visit https://docs.oracle.com/javase/tutorial/i18n/resbundle/propfile.html site for more information.