Tuesday, July 24, 2012

Java O-O Concepts

                                       Classes and objects                                      
class describes the data and the methods of its objects. Every object belongs to some class.
An object contains data (instance variables) representing its state, and instance methods, which are the things it can do.
A class may also contain its own data (class variables) and class methods. The keyword static denotes such data and methods.
An object "knows" what class it belongs to, and can use class data and class methods, but a class does not "know" about its objects.
Classes form a hierarchy (tree), with Object at the root. Every class, except Object, has one and only one immediate superclass, but that class has its own immediate superclass, and so on all the way up to Object at the root, and all of these are superclasses of the class. The keyword extends denotes the immediate superclass.
A class contains one or more constructors for making new objects of that class. If (and only if) the programmer does not write a constructor, Java provides a default constructor with no arguments. The default constructor sets instance variables as follows: numeric types are set to zero, boolean variables are set to falsechar variables are set to '\0', and object variables are set to null.
The purpose of a constructor is to create an object in a valid state. No other work should be done in a constructor.
When a constructor executes, the very first thing it does is call the constructor for its superclass. You can write this constructor call explicitly, with super(...);, or you can let it implicitly call the default constructor.
A constructor for a class can call another constructor for the same class by putting this(...); as the first thing in the constructor. This allows you to avoid repeating code.
Objects are declared just like primitive values, with the syntax ClassName objectName; but are not defined (allocated space and given a value) until you create one by calling the constructor with the keyword new.
Classes inherit all the data and all the methods of their superclasses, but do not inherit constructors.
You can assign an object of a class to a variable (that is, variable = object) declared to be of that class or any of its superclasses (thus, you can assign any object to a variable of type Object). If you have an object in a more general variable or expression (for example, a String value in an Object variable), you can cast it to the correct type with the syntax (type)variable or (type)(expression).
Casting an object to a more general type is called upcasting, and is always legal. Casting an object to a more specific type is called downcasting, and Java inserts a run-time check to ensure that the cast is legal. Casting does not affect what the object is, it only changes what fields and methods are available on the object at the position the cast occurs.
A class that is declared as final may not be extended by subclasses.
The instanceof operator tests whether its left operand (an object) is an instance of its right operand (a class or interface). The result will be true if the right operand is the class or any superclass of the object. Well-designed programs have very little need for the instanceof operator.
A Java source file may contain only one public class, though it may contain additional non-public classes. The name of the file must be the same as the name of the class, but with the .java extension.
Classes should be as self-contained and independent as it is reasonable to make them. The interface (the fields and methods it makes available outside the class) should be kept small.
An object is responsible for keeping itself in a valid state. Therefore, it should limit write access to essential fields.
                               Access                                                   

Variables and methods are accessed by name.
There are three dimensions to accessing names: namespaces, scope, and access modifiers.
Java uses six different namespaces: package names, type names, field (variable) names, method names, local variable names (including parameters), and labels. Identical names of different types do not conflict; for example, a method may be named the same as a local variable. However, it's best to avoid reusing names in this manner.
The scope of a name is the part of a class in which it can be seen.
  • A variable declared anywhere in a class can be seen everywhere in a class.
  • The scope of a method's formal parameters is the entire method.
  • The scope of a variable declared in a block (indicated by braces, { }) extends from the declaration to the closing brace. A method body is always a block.
  • The scope of a variable declared in the initialization part of a for loop is the entire for loop.
Class variables and class methods (denoted by the keyword static) can be used anywhere within the class.
Instance variables and instance methods can be used anywhere within the class except in static methods.
Within an instance method, the keyword this refers to the object currently executing the method.
When an instance variable and a formal parameter have the same name, the name refers to the formal parameter; prefix the name with this. to refer to the instance variable.
To refer to an instance name in a different object, use the syntax otherObject.name. To refer to a class (static) name in a different class, use the syntax OtherClass.name.
You can refer to a name (class or instance) in another class if and only if you have access privileges. Possible access privileges are:
  • public : You can access it from anywhere.
  • protected : You can access it from any other class in the same directory (folder), or from any subclass.
  • package (default) : You can access it from any other class in the same directory.
  • private : You cannot access it from outside the class.
You can refer to a name in a class in another package in either of two ways:
  • You can use the fully-qualified name, for instance java.awt.Color.red
  • You can import a specific class or (with *) all classes in a given package, then use the name as if you had defined it yourself.

Methods


method is a named executable chunk of code.
All executable statements must be in methods. (Exception: "initialization blocks," not covered here.)
A method has a signature consisting of its name and the number and types of its parameters (also called "arguments"). The parameters in the method declaration are its formal parameters.
A method has a return type, which is not part of its signature. If the return type is other than void, then the method must return a value of the specified type.
A method may have local variables (also called method variables). These follow the scope rules, and are never available anywhere outside the method. The concepts staticpublicprotected, package, and private do not apply to local variables. Formal parameters are a kind of local variable.
Every method must have a signature that is unique within its class. Methods in other classes (even superclasses and subclasses) may have the same signature.
An instance method is executed by sending a message to its object. The message consists of: a reference to the object (typically its name), a dot, the name of the method, and zero or more actual parameters enclosed in parentheses.
A class method is executed by sending a message to the class. The message consists of: the name of the class, a dot, the name of the method, and zero or more actual parameters enclosed in parentheses.
When a message is sent, and before the method executes, the values of the actual parameters are copied into the corresponding formal parameters. Then the method body executes. Then the return value replaces the message, and all local names are forgotten.

Polymorphism

The two kinds of polymorphism are overloading and overriding.Overloading occurs when a class declares two or more methods with the same name but different signatures. When a message is sent to an object or class with overloaded methods, the method with the best matching signature is the one that is used ("invoked").
  • If the message and the method have a different number of parameters, no match is possible.
  • If the message and the method have exactly the same types of parameters, that is the best possible match.
  • Messages with specific actual parameter types can invoke methods with more general formal parameter types. For example if the formal parameter type is Object, an actual parameter of typeString is acceptable (since a String value can be assigned to an Object variable). If the formal parameter is type double, an actual parameter of type int can be used (for similar reasons).
  • If there is no clear best match, Java reports a syntax error.
Overriding occurs when a class declares a method with the same signature as that of an inherited method. When a message is sent to the object (or class, if it's a class method), the locally-defined method is the one that is used.
  • Overriding is commonly used to make methods more specific.
  • When a method name is overridden, you can still invoke the superclass' method (from inside the class) with the syntax super.name(parameters).
  • From outside the class, you can cast an object to its superclass and then invoke the method, with the syntax ((Superclass)object).name(parameters).
  • Although the return type is not part of the signature, an overriding must have the same return type as the method it overrides.
  • The overriding method may not throw any exception types in addition to those thrown by the method it overrides (although it may throw fewer exception types).
A class can declare a variable with the same name as an inherited variable, thus "hiding" or shadowing the inherited version. (This is like overriding, but for variables.)
  • Shadowing should be avoided.
  • When shadowing does happen, you can access the superclass name by either the syntax super.name or by casting the object to its superclass, with the syntax ((Superclass)object).name.
Interfaces and abstract classes

The purpose of interfaces and abstract methods is to ensure that any classes derived from them will share the same set of methods.An abstract method is a method that is declared but not defined. It is declared with the keyword abstract, and has a header like any other method, but ends with a semicolon instead of a method body.
An abstract class is one that contains one or more abstract methods; it must itself be declared with the abstract keyword. A class may be declared abstract even if it does not contain any abstract methods. A non-abstract class is sometimes called a concrete class.
An abstract class cannot be instantiated; that is, no objects of that class can be created. Instead, you can create subclasses that define (in the usual way) the inherited abstract methods, and these subclasses can be instantiated.
An interface is declared with the keyword interface instead of the keyword class. An interface may contain only abstract methods and definitions of constants (that is, final variables). The keywordabstract before each method is optional.
A class may extend only one other class, but it may implement any number of interfaces. The syntax is: class Class extends Superclass implements Interface1,Interface2, .... When a class extends an interface, it may implement (define) some or all of the inherited abstract methods. A class must itself be declared abstract if it inherits abstract methods that it does not define.
A variable may be declared to have a type that is an abstract class or an interface; any object whose type implements or extends the variable's type may be assigned to that variable. The instanceofoperator may take a class, abstract class, or interface as its right operand.

Inner classes

An inner class is a class declared within another class. The four kinds of inner class are: (1) member class, (2) static member class, (3) local inner class, and (4) anonymous inner class. Unlike "outer" classes, the usual scope rules apply to inner classes.
member class is defined at the top level of the class, along with fields and methods. It may have the same access modifiers as variables (publicprotectedpackagestaticfinal), and is accessed in much the same way as variables of that class.
static member class is defined like a member class, but with the keyword static. Despite its position inside another class, a static member class is actually an "outer" class--it has no special access to names in its containing class. To refer to the static inner class from a class outside the containing class, use the syntax OuterClassName.InnerClassName. A static member class may contain static fields and methods.
local inner class is defined within a method, and the usual scope rules apply to it. It is only accessible within that method, therefore access restrictions (publicprotectedpackage) do not apply. However, because objects (and their methods) created from this class may persist after the method returns, a local inner class may not refer to parameters or non-final local variables or of the method.
An anonymous inner class is one that is declared and used to create one object (typically as a parameter to a method), all within a single statement. The anonymous inner class may either extend a class or implement an interface; the syntax is the same: new Super(parameters){methods}, where Super is the name of the extended class or implemented interface, parameters are the parameters to the constructor for that class or interface (usually just ()), and methods override any inherited methods.
The keyword static may not be used within any inner class except a static member class.


Wednesday, June 13, 2012

Struts 2 Interview Questions

1) How to create an action with Struts2?
 Creating an action in Struts2 is very different from Struts1 in the sense that there is no mandatory requirement to extend a class from the struts library. A Java bean/POJO which has the private member variables and public getters and setters is sufficient to become a struts action class. As far as execute() method of Struts1 is concerned, a method with return type of String is sufficient. The method name is to be specified in the struts.xml. This change is done so that the testing of struts based application can be done easily.

2) In struts.xml, what does the attribute "method" stands for in the "action" tag?
The method attribute tells the name of method to be invoked after setting the properties of the action class. This attribute can either hold the actual name of the method or the index of the result mapping.
For example:
<action class="com.company.app.Login" method="login" name="login">
    <result name="success">/success.jsp</result>
</action>
<action class="com.company.app.Login" method="{1}" name="login">
    <result name="login">/success.jsp</result>
</action>
In both the examples, the method being invoked by Struts will be login with the signature as 
public String login()


3) If I have an ArrayList of say Employees class in the struts action (which may be fetched from the database), how can I iterate and display the Employee Id and Employee Name on the next JSP being shown? Assume the name of ArrayList to be employee
We can iterate such a collection as:

<s:iterator value="employee">
       <s:property value="name"></s:property>
      <s:property value="id"></s:property>
</s:iterator>

4) What is the advantage of having a POJO class as an action?
As mentioned in the first question, the POJO class is light weight and easy to test with frameworks like Junit. Moreover, there is no need to create separate ActionForms to hold the values from the source web page.

5) What is the advantage of extending the action class from ActionSupport class?
The use of ActionSupport class provides the features like validation, locale support and serialization to an action,

6) How can we get rid of .action at the end of URL's in struts 2?
You can get the answer to that question from one my other blog post at:

7) How can one integrate Spring IoC with Struts 2?
Struts 2 comes with support for Spring and Spring can be used to inject beans to various classes. It can also be used to inject properties to the action class of struts 2. For configuring Spring, contextLoaderListener can be configured.

8) Describe the flow of a request in a Struts 2 web application?
 It can be best understood by using a diagram. Please refer the following URL for understanding the same.

9) What tool/IDE/frameworks do you use to write code in a Struts 2 web application?
Mostly it is MyEclipse 9 which has excellent support for struts 2. Netbeans 7  has support for Struts 1 but not Struts 2. Other that the IDE one can also mention tools like DreamWeaver, Spring, Hibernate, XMLSpy etc.

10) What are the steps to migrate a web application written with Struts 1 to Struts 2?
This involves moving ActionForms of Struts1 to POJO properties of Struts 2.
Converting Struts1 struts-config.xml to struts.xml of Struts2. 
Rewriting the Struts action classes for Struts 2.


Design pattern interview questions for Senior and experienced level

1. Give an example where you prefer abstract class over interface ?
This is common but yet tricky design interview question. both interface and abstract class follow "writing code for interface than implementation" design principle which adds flexibility in code, quite important to tackle with changing requirement. here are some pointers which help you to answer this question:
1. In Java you can only extend one class but implement multiple interface. So if you extend a class you lost your chance of extending another class.
2. Interface are used to represent adjective or behavior e.g. Runnable, Clonable, Serializable etc, so if you use an abstract class to represent behavior your class can not be Runnable and Clonable at same time because you can not extend two class in Java but if you use interface your class can have multiple behavior at same time.
3. On time critical application prefer abstract class is slightly faster than interface.
4. If there is a genuine common behavior across the inheritance hierarchy which can be coded better at one place than abstract class is preferred choice. Some time interface and abstract class can work together also where defining function in interface and default functionality on abstract class.


2. Design a Vending Machine which can accept different coins, deliver different products?
This is an open design question which you can use as exercise, try producing design document, code and Junit test rather just solving the problem and check how much time it take you to come to solution and produce require artifacts, Ideally this question should be solve in 3 hours, at least a working version.

3. You have a Smartphone class and will have derived classes like IPhone, AndroidPhone,WindowsMobilePhone
can be even phone names with brand, how would you design this system of Classes.
This is another design pattern exercise where you need to apply your object oriented design skill to come with a design which is flexible enough to support future products and stable enough to support changes in existing model.

4. When do you overload a method in Java and when do you override it ?
Rather a simple question for experienced designer in Java. if you see different implementation of a class has different way of doing certain thing than overriding is the way to go while overloading is doing same thing but with different input. method signature varies in case of overloading but not in case of overriding in java.

5. Design ATM Machine ?
We all use ATM (Automated Teller Machine) , Just think how will you design an ATM ? for designing financial system one must requirement is that they should work as expected in all situation. so no matter whether its power outage ATM should maintain correct state (transactions), think about locking, transaction, error condition, boundary condition etc. even if you not able to come up exact design but if you be able to point out non functional requirement, raise some question , think about boundary condition will be good progress.

6. You are writing classes to provide Market Data and you know that you can switch to different vendors overtime like Reuters, wombat and may be even to direct exchange feed , how do you design your Market Data system.
This is very interesting design interview question and actually asked in one of big investment bank and rather common scenario if you have been writing code in Java. Key point is you will have a MarketData interface which will have methods required by client e.g. getBid(), getPrice(), getLevel() etc and MarketData should be composed with a MarketDataProvider by using dependency injection. So when you change your MarketData provider Client won't get affected because they access method form MarketData interface or class.

7. Why is access to non-static variables not allowed from static methods in Java
You can not access non-static data from static context in Java simply because non-static variables are associated with a particular instance of object while Static is not associated with any instance. 

8. Design a Concurrent Rule pipeline in Java?
Concurrent programming or concurrent design is very hot now days to leverage power of ever increasing cores in
advanced processor and Java being a multi-threaded language has benefit over others. Do design a concurrent system key point to note is thread-safety, immutability, local variables and avoid using static or instance variables. you just to think that one class can be executed by multiple thread a same time, So best approach is that every thread work on its own data, doesn't interfere on other data and have minimal synchronization preferred at start of pipeline. This question can lead from initial discussion to full coding of classes and interface but if you remember key points and issues around concurrency e.g. race condition, deadlock, memory interference, atomicity, ThreadLocal variables  etc you can get around it.

10 Tricky Java Interview Questions

Here are some Java interview questions which are  un-common
  1. What is the performance effect of a large number of import statements which are not used?
    Answer: They are ignored if the corresponding class is not used.
  2. Give a scenario where hotspot will optimize your code?
    Answer: If we have defined a variable as static and then initialized this variable in a static block then the Hotspot will merge the variable and the initialization in a single statement and hence reduce the code.
  3. What will happen if an exception is thrown from the finally block?
    Answer: The program will exit if the exception is not catched in the finally block.
  4.  How does decorator design pattern works in I/O classes?
    Answer:  The various classes like BufferedReader , BufferedWriter workk on the underlying stream classes. Thus Buffered* class will provide a Buffer for Reader/Writer classes.
  5. If I give you an assignment to design Shopping cart web application, how will you define the architecture of this application. You are free to choose any framework, tool or server?
    Answer:  Usually I will choose a MVC framework which will make me use other design patterns like Front Controller, Business Delegate, Service Locater, DAO, DTO, Loose Coupling etc. Struts 2 is very easy to configure and comes with other plugins like Tiles, Velocity and Validator etc. The architecture of Struts becomes the architecture of my application with various actions and corresponding JSP pages in place.
  6. What is a deadlock in Java? How will you detect and get rid of deadlocks?
    Answer:  Deadlock exists when two threads try to get hold of a object which is already held by another object.
  7. Why is it better to use hibernate than JDBC for database interaction in various Java applications?
    Answer:  Hibernate provides an OO view of the database by mapping the various classes to the database tables. This helps in thinking in terms of the OO language then in RDBMS terms and hence increases productivity.
  8. How can one call one constructor from another constructor in a class?
    Answer:  Use the this() method to refer to constructors.
  9. What is the purpose of intern() method in the String class?
    Answer:  It helps in moving the normal string objects to move to the String literal pool
  10. How will you make your web application to use the https protocol?
    Answer:  This has more to do with the particular server being used  than the application itself. Here is how it can be done on tomcat:

Monday, June 11, 2012

Java performance questions and answers: overview and profiling cpu | 400+ Java Interview Questions and Answers blog

400+ Java Interview Questions and Answers blog: Why prepare with 400+ Java Interview Questions and...

400+ Java Interview Questions and Answers blog: Why prepare with 400+ Java Interview Questions and...: What are these 16 key areas?  Language Fundamentals ( LF ) Specification Fundamentals ( SF ) Platform Fundamentals ( PF ) Design C...

Java stack data structure interview questions and answers

The Java Collection library is one of the most frequently used libraries.The LIFO access mechanism used by a stack has many practical uses.  For example, Evaluation of expressions / syntax Parsing, validating and parsing XML, undo sequence in a text editor, pages visited history in a web browser, etc. Here are a few Java based interview questions and answers on a stack.

What LIFO implementation would you use in Java?
The Vector based Stack class is a legacy and the Javadoc documentation for this class states that Deque should be used instead because it provides better LIFO operation support. Implementations of Deque are typically expected to perform better than Stack. J2SE 5 introduced a Queue interface and the Deque interface extends this interface. The Deque interface supports should be pronounced "deck" rather than "de-queue" and is not related to dequeue used to indicate removal from a queue. The double-ended queue supports addition or removal of elements from either end of the data structure, so it can be used as a queue (first-in-first-out/FIFO) or as a stack (last-in-first-out/LIFO).

Note:  The legacy Vector class uses internal synchronization, and it is rarely good enough for actual consistency, and can slow down execution when it is not really needed. The new java.util.concurrent package provides a more efficient way of thread-safety.

Can you write a program to evaluate if a given string input has proper closing bracket for every opening bracket?
A. Firstly, think of the pseudo code. The pseudo-code goes as follows.

1. Store every opening parenthesis (i.e. a LHS parenthesis) in a stack. This will enable LIFO.
2. When you encounter a closing parenthesis (i.e. RHS parenthesis ), pop the last entry, which should be the corresponding opening parenthesis.
3. If not found, then the parentheses are not matched.

If required, draw a diagram as shown below.





Here is a sample program to illustrate a Stack (i.e. LIFO) in action in evaluating if a program has balanced parentheses. The enum constants class that defines the parentheses.



public enum PARENTHESIS {
 LP('('), RP(')'), LB('{'), B('}'), LSB('['), RSB(']');
  char symbol;
 PARENTHESIS(Character symbol) {
  this.symbol = symbol;
 }

 char getSymbol() {
  return this.symbol;
 }


Now, the stack in action using its LIFO mechanism to marry a closing parenthesis (i.e RHS) with an opening parenthesis (i.e. LHS). If you find any LHS parenthesis, push it into a stack, and when you find a RHS parenthesis, pop the stack to see if you have a corresponding LHS parenthesis.




















import java.util.ArrayDeque;
import java.util.Deque;
public class Evaluate {
  //stores the parentheses
 final Deque<character> paranthesesStack = new ArrayDeque<character>();

 public boolean isBalanced(String s) {
   for (int i = 0; i < s.length(); i++) {
   if (s.charAt(i) == PARENTHESIS.LP.getSymbol() ||
       s.charAt(i) == PARENTHESIS.LB.getSymbol() ||
       s.charAt(i) == PARENTHESIS.LSB.getSymbol())
     
     paranthesesStack.push(s.charAt(i));// auto boxing takes place
                                       // push the opening parentheses
    //for each RHS parenthesis check if there is a matching LHS Parenthesis
   //if the stack is empty or does not have a matching LHS parenthesis
   //then not balanced.
   else if (s.charAt(i) == PARENTHESIS.RP.getSymbol()){ 
    if (paranthesesStack.isEmpty() || paranthesesStack.pop()
        !=   PARENTHESIS.LP.getSymbol())
     return false;
   }
    else if (s.charAt(i) == PARENTHESIS.RB.getSymbol() ) {
    if (paranthesesStack.isEmpty() 
      || paranthesesStack.pop() !=PARENTHESIS.LB.getSymbol() )
     return false;
   }
    else if (s.charAt(i) == PARENTHESIS.RSB.getSymbol()) {
    if (paranthesesStack.isEmpty() 
       || paranthesesStack.pop() != PARENTHESIS.LSB.getSymbol())
     return false;
   }
  }
   return paranthesesStack.isEmpty();
   //if the stack is empty, then all matched well, otherwise not matched.
 }
}

Note: ArrayDeque is not thread-safe and does not allow for elements of the data structure to be null. The concurrent package has BlockingDeque and LinkedBlockingDequeue.

Finally, a simple JUnit class to test.


import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
 public class EvaluateTest {
  
 Evaluate eval = null;
  
 @Before
 public void setUp(){
  eval = new Evaluate();
 }
  
 @Test
 public void testPositiveIsBalanced(){
   boolean result = eval.isBalanced("public static void main(String[] args) {}");
      Assert.assertTrue(result);  
       
 }
  
 @Test
 public void testNegativeIsBalanced(){
   boolean result = eval.isBalanced("public static void main(String[ args) {}");   // missing ']'
      Assert.assertFalse(result);
       
      result = eval.isBalanced("public static void main(String[] args) }");          // missing '{'
      Assert.assertFalse(result);
       
       
      result = eval.isBalanced("public static void main String[] args) {}");        // missing '('
      Assert.assertFalse(result);
       
 }
}
Tip: When testing, test positive and negative scenarios.

Note: The above example is shown to illustrate how a LIFO mechanism can be used to determine if the parentheses are balanced. The actual implementation is far from being optimum. Where ever there is a large block of if-else or switch statements, one should think about an object oriented solution.

Why Deque interface is different from other collection classes?
In Deque, You can insert and delete the objects from the both start and end of the the collection. Whereas in a normal collection, inserts/deletes are happening at last only.

What are the different ways to look at the trace of your program execution?
1.Java is a stack based language, and the program execution is pushed and popped out of a stack. When a method is entered into, it is pushed into a stack, and when that method invokes many other methods, they are pushed into the stack in the order in which they are executed. As each method completes its execution, they are popped out of the stack in the LIFO order. Say methodA( ) invoked methodB( ), and methodB( ) invoked methodC ( ), when execution of methodC( ) is completed, it is popped out first, and then followed by methodB( ) and then methodA( ). When an exception is thrown at any point, a stack trace is printed for you to be able to find where the issue is.


2. A Java developer can access a stack trace at any time. One way to do this is to call


Thread.currentThread().getStackTrace() ; //handy for tracing

You could get a stack trace of all the threads using the Java utilities such as jstack, JConsole or by sending a kill -quit signal (on a Posix operating system) or <ctrl><break> on WIN32 platform to get a thread dump. You could also use the JMX API as shown below. ThreadMXBean is the management interface for the thread system of the JVM.



ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);
for (ThreadInfo info : infos) { 
    StackTraceElement[] elems = info.getStackTrace(); 
 //...do something
}

The thread dumps are very useful in identifying concurrency issues like dead locks, contention issues, thread starvation, etc.

Is recursive method calls possible in Java?
Yes. Java is stack based and because of its LIFO (Last In First Out) property, it remembers its 'caller'. So it knows whom to return when the method has to return.

How would you go about analysing stack traces correctly?
1. One of the most important concepts of correctly understanding a stack trace is to recognize that it lists the execution path in reverse chronological order from most recent operation to earliest operation. That is, it is LIFO.
2. The stack trace below is simple and it tells you that the root cause is a NullPointerException on Class C. So you look at the top most class.

Exception in thread "main" java.lang.NullPointerException
        at com.myapp.ClassC.methodC(ClassC.java:16)
        at com.myapp.ClassB.methodB(ClassB.java:25)
        at com.myapp.ClassA.main(ClassA.java:14)
3. The stack trace can get more complex with multiple "caused by" clauses, and in this case you usually look at the bottom most "caused by". For example,

Exception in thread "main" java.lang.IllegalStateException: ClassC has a null property
        at com.myapp.ClassC.methodC(ClassC.java:16)
        at com.myapp.ClassB.methodB(ClassB.java:25)
        at com.myapp.ClassA.main(ClassA.java:14)
Caused by: com.myapp.MyAppValidationException
        at com.myapp.ClassB.methodB(ClassB.java:25)
        at com.myapp.ClassC.methodC(ClassC.java:16)
        ... 1 more
Caused by: java.lang.NullPointerException
        at com.myapp.ClassC.methodC(ClassC.java:16)
        ... 1 more

The root cause is the last "caused by", which is a NullPointerException on ClassC

4. When you use plethora of third-party libraries like Spring, Hibernate, etc, your stack trace's "caused by" can really grow and you need to look at the bottom most "caused by" that has the package relevant to you application like com.myapp.ClassC and skip library specific ones like org.hibernate.exception.*.

Can you reverse the following numbers {1, 4, 6, 7, 8, 9}?
There are a number of ways to achieve this. Speaking of LIFO, the following example illustrates using a stack based implementation.


import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;  

public class ReverseNumbers { 
 public static void main(String[] args) {
  Integer[] values = {1, 4, 6, 7, 8, 9};
  Deque<integer> numberStack = new ArrayDeque<integer>(10);
   
  for (int i = 0; i < values.length; i++) {
   numberStack.push(values[i]);  // push the numbers in given order
  }
   
  Integer[] valuesReversed = new Integer[values.length];
   
  int i = 0;
  while (!numberStack.isEmpty()) {
   valuesReversed[i++] = numberStack.pop();
    // pop it - as this happens in reverse order
    // i++ is a post increment i.e.
    // assign it and then increment it
    // for the next round
  }
   System.out.println(Arrays.deepToString(valuesReversed));
   
 }
}

The output will be

[9, 8, 7, 6, 4, 1]

Java Collection Interview Questions and Answers

Java Collections Framework (i.e. Data structures)  contains most commonly asked Java interview questions. A good understanding of Collections framework is required to understand and leverage many powerful features of Java technology. Here are a few important practical questions which can be asked in a Core Java interview.

Q. What are the common data structures, and where would you use them?
A.  Many leave out Trees and Graphs.  Trees and Graphs are very useful data structures as well. As you provide your answer,  the interviewer may further quiz you on

Q. How you would go about implementing your own List, Set, and Map?

Whilst it is not recommended to write your own implementation when Java provides proven and tested implementations, the interviewer is testing your understanding on data structures. My book entitled "Core Java Career Essentials" covers this in more detail with diagrams, examples, and code.


Here are the common data structures.

Arrays are the most commonly used data structure. Arrays are of fixed size, indexed, and all containing elements are of the same type (i.e. a homogenous collection). For example, storing employee details just read from the database as EmployeeDetail[ ], converting and storing a string as a byte array for further manipulation or processing, etc. Wrap an array in a class to protect it from being inadvertently altered. This would be true for other data structures as well.

Lists are known as arrays that can grow. These data structures are generally backed by a fixed sized array and they re-size themselves as necessary. A list can have duplicate elements. For example,  adding new line items to an order that stores its line items as a list, removing all expired products from a list of products, etc. Initialize them with an appropriate initial size to minimize the number of re-sizes

Sets are like lists but they do not hold duplicate elements. Sets can be used when you have a requirement to store unique elements.

Stacks allow access to only one data item, which is the last item inserted (i.e. Last In First Out - LIFO). If you remove this item, you can access the next-to-last item inserted, and so on. The LIFO is achieved through restricting access only via methods like peek( ), push( ), and pop( ). This is useful in many programing situations like parsing mathematical expressions like (4+2) * 3, storing methods and exceptions in the order they occur, checking your source code to see if the brackets and braces are balanced properly, etc.

The LIFO access mechanism used by a stack has many practical uses.  For example, Evaluation of expressions / syntax Parsing, validating and parsing XML, undo sequence in a text editor, pages visited history in a web browser, etc. Java interview questions and answers on stack data structure


Queues are somewhat like a stack, except that in a queue the first item inserted is the first to be removed (i.e. First In First Out – FIFO). The FIFO is achieved through restricting access only via methods like peek( ), offer( ), and poll( ). For example,  waiting in a line for a bus, a queue at the bank or super market teller, etc.

Here is a code example of a blocking queue with multiple threads.


LinkedLists are data structures made of nodes, where each node contains data and a reference to the next node, and possibly  to the previous node as well for a doubly linked list. For example, a stack or queue can be implemented with a linked list or a doubly linked list because you can insert and delete at both ends. There would also be other situations where data will be frequently inserted and deleted from the middle. The Apache library provides a TreeList implementation, which is a good replacement for a LinkedList as it performs much better than a LinkedList at the expense of using a little more memory.  This means a LinkedList is rarely a good choice of implementation.


ArrayList is a good general purpose list implementation. An ArrayList is faster than a TreeList for most operations except inserting and removing in the middle of the list. A TreeList implementation utilizes a tree structure internally to ensure that all insertions and removals are O(log n). This provides much faster performance than both an ArrayList and a LinkedList where elements are inserted and removed repeatedly from anywhere in the list. 


?
1
2
3
4
5
class Link {
   private int id;                    // data
   private String name;               // data
   private Link next;                 // reference to next link
}


HashMaps are amortized constant-time access data structures that map keys to values. This data structure is backed by an array. It uses a hashing functionality to identify a location, and some type of collision detection algorithm is used to handle values that hash to the same location. For example, storing employee records with employee number as the key, storing name/value pairs read from a properties file, etc. Initialize them with an appropriate initial size to minimize the number of re-sizes.

Trees are the data structures that contain nodes with optional data elements and one or more child elements, and possibly each child element references the parent element to represent a hierarchical or ordered set of data elements.  For example, a hierarchy of employees in an organization, storing the XML data as a hierarchy, etc.  If every node in a tree can have utmost 2 children, the tree is called a binary tree. The binary trees are very common because the shape of a binary tree makes it easy to search and insert data. The edges in a tree represent quick ways to navigate from node to node.


Java does not provide an implementation for this but it can be easily implemented as shown below. Just make a class Node with an ArrayList holding links to other Nodes.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package bigo;
 
import java.util.ArrayList;
import java.util.List;
 
public class Node {
    private String name;
    private List<node> children = new ArrayList<node>( );
    private Node parent;
     
    public Node getParent( ) {
        return parent;
    }
 
    public void setParent(Node parent) {
        this.parent = parent;
    }
 
    public Node(String name) {
        this.name = name;
    }
     
    public void addChild(Node child) {
        children.add(child);
    }
     
    public void removeChild(Node child) {
        children.remove(child);
    }
    
    public String toString( ) {
        return name;
    }
 }


Graphs are data structures that represent arbitrary relationships between members of any data sets that can be represented as networks of nodes and edges. A tree structure is essentially a more organized graph where each node can only have one parent node. Unlike a tree, a graph's shape is dictated by a physical or abstract problem. For example, nodes (or vertices)  in a graph may represent cities, while edges may represent airline flight routes between the cities.




To make a Java graph class, you will have to work out the way in which the information can be stored and accessed. A graph will be using some of the data structures mentioned above. The Java API does not provide an implementation for this. But there are a number of third party libraries like  JUNG, JGraphT, and JDSL (does not seem to support generics).The book "Core Java Career Essentials" covers working examples using Java.

Q. What do you know about the big-O notation and can you give some examples with respect to different data structures?
A. The Big-O notation simply describes how well an algorithm scales or performs in the worst case scenario as the number of elements in a data structure increases.  The Big-O notation can also be used to describe other behavior such as memory consumption. At times you may need to choose a slower algorithm because it also consumes less memory. Big-o notation can give a good indication about performance for large amounts of data, but the only real way to know for sure is to have a performance benchmark with large data sets to take into account things that are not considered in Big-O notation like paging as virtual memory usage grows, etc. Although benchmarks are better, they aren't feasible during the design process, so Big-O complexity analysis is the choice.

The algorithms used by various data structures for different operations like search, insert and delete fall into the following performance groups like constant-time O(1), linear O(n), logarithmic O (log n), exponential O (c to the power n), polynomial O(n to the power c), quadratic O (n to the power 2) and factorial O (n!) where n is the number of elements in the data structure. It is generally a tradeoff between performance and memory usage. Here are some examples.

Example 1: Finding an element in a HashMap is usually a constant-time, which is  O(1) . This is a constant time because a hashing function is used to find an element, and computing a hash value does not depend on the number of elements in the HashMap.

Example 2:  Linear search of an array, list, and LinkedList is linear, which is O(n). This is linear because you will have to search the entire list. This means that if a list is twice as big, searching it will take twice as long.

Example 3: An algorithm that needs to compare every element in an array to sort the array has polynomial complexity, which is O (n2). A nested for loop is O (n2).  An example is shown under sorting algorithms.

Example 4: Binary search of a sorted array or ArrayList is logarithmic, which is O(log n). Searching an element in a LinkedList normally requires O(n). This is one of the disadvantages of LinkedList over the other data structures like an ArrayList or array offering a O (log n) performance, which offers better performance than O(n)  as the number of elements increases. A logarithmic running times mean, if 10 items take at most x amount of time, 100 items will take say at most 2x amount of time, and 10,000 items will take at most  4x. If you plot this on a graph, the time decreases as  n (i.e. number of items) increases.


Q. What can you tell about the performance of a HashMap compared to a TreeMap? Which one would you prefer?
A.  A balanced tree does have O (log n) performance. The TreeMap class in Java maintains key/value objects in a sorted order by using a red-black tree. A red-black tree is a balanced binary tree. Keeping the binary tree balanced ensures the fast insertion, removal, and look-up time of O (log n). This is not as fast as a HashMap, which is O(1) ,  but the TreeMap has the advantage of that the keys are in sorted order which opens up a lot of other capabilities.  



Q. Which one to choose? 

The decision as to using an unordered collection like a HashSet  or HasMap versus   using a sorted data structure like a TreeSet  or TreeMap depends mainly on the usage pattern, and to some extent on the data size and the environment you run it on.   The practical reason for keeping the elements in sorted order is for frequent and faster retrieval of sorted data if the inserts and updates are frequent. If the need for a sorted result is infrequent like prior to producing a report or running a batch process, then maintaining an unordered collection and sorting them only when it is really required with Collections.sort(...) could sometimes be more efficient than maintaining the ordered elements. This is only an opinion, and no one can offer you a correct answer. Even the complexity theories like Big-O notation like O(n) assume possibly large values of n.  In practice, a O(n) algorithm can be much faster than a O(log n) algorithm, provided the data set that is handled is sufficiently small. One algorithm might perform better on an AMD processor than on an Intel. If your system is set up to swap, disk performance need to be considered. The only way to confirm the efficient usage is to test and measure both performance and memory usage with the right data size. Measure both the approaches on your chosen hardware to determine, which is more appropriate.


Q. What is the tradeoff between using an unordered array versus an ordered array?
A. The major advantage of an ordered array is that the search times are much faster with O (log n) than an unordered array, which is O (n) for larger values of n. The disadvantage of an ordered array is that the insertion takes longer (i.e. O (n) ) because all the data with higher values need to be moved to make room. The insertion for an unordered array takes constant time of O(1). This means, it does not depend on the number of elements. The following code snippet demonstrates adding an element to both ordered and unordered array.

Inserting an element into an unsorted array


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package bigo;
 
import java.util.Arrays;
 
public class InsertingElementsToArray {
 
    public static void insertUnsortedArray(String toInsert) {
 
        String[ ] unsortedArray = { "A", "D", "C" };
 
        String[ ] newUnsortedArray = new String[unsortedArray.length + 1];
        System.arraycopy(unsortedArray, 0, newUnsortedArray, 0, 3);
        newUnsortedArray[newUnsortedArray.length - 1] = toInsert;
        System.out.println(Arrays.toString(newUnsortedArray));
    }
 
    public static void main(String[ ] args) {
        insertUnsortedArray("B");
    }
}

Inserting an element into a sorted array


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package bigo;
 
import java.util.Arrays;
 
public class InsertingElementsToArray {
 
    public static void insertSortedArray(String toInsert) {
 
        String[ ] sortedArray = { "A", "C", "D" };
 
        /*
         * Binary search returns the index of the search item
         * if found, otherwise returns the minus insertion point. This example
         * returns index = -2, which means the elemnt is not found and needs to
         * be inserted as a second element.
         */
        int index = Arrays.binarySearch(sortedArray, toInsert);
 
        if (index < 0) {                                   // not found.
 
            // array indices are zero based. -2 index means insertion point of
            // -(-2)-1 = 1,  so insertIndex = 1
            int insertIndex = -index - 1;
 
            String[ ] newSortedArray = new String[sortedArray.length + 1];
            System.arraycopy(sortedArray, 0, newSortedArray, 0,  insertIndex);
            System.arraycopy(sortedArray, insertIndex,
                    newSortedArray, insertIndex + 1,  sortedArray.length - insertIndex);
            newSortedArray[insertIndex] = toInsert;
            System.out.println(Arrays.toString(newSortedArray));
        }
    }
 
    public static void main(String[ ] args) {
        insertSortedArray("B");
    }
}

So the decision depends on the usage pattern. Ask yourself the following questions. Do I have more inserts/deletes or search? What is the maximum number of elements likely to be stored in this array? How often do I need the sorted data? And finally what does my performance benchmark show?

Q. How do you get an immutable collection?
A. This functionality is provided by the Collections class, which is a wrapper implementation using the decorator design pattern.


1
2
3
4
5
6
7
8
9
10
11
public class ReadOnlyExample {
    public static void main(String args[ ]) {
        Set<string> set = new HashSet<string>( );
        set.add("Java");
        set.add("JEE");
        set.add("Spring");
        set.add("Hibernate");
        set = Collections.unmodifiableSet(set);
        set.add("Ajax");                                           // not allowed.
  }
}

Q. What does the following code do? Can the LinkedHashSet be replaced with a HashSet?

1
2
3
4
5
6
7
8
9
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
 
public class CollectionFunction {
    public <e> List<e> function (List <e> list) {
          return new ArrayList<e>(new LinkedHashSet<e>(list));
    }
}

A. The above code removes duplicates from a supplied list by passing it through an implementation of a Set interface. In this case, a LinkedHashSet is used to honor the ordering by implementing a SortedSet interface. If ordering is not required, the LinkedHashSet can be replaced with a HashSet.

Q. What are some of the best practices relating to the Java Collection framework?
A.

  • Choose the right type of data structure based on usage patterns like fixed size or required to grow, duplicates allowed or not, ordering is required to be maintained or not, traversal is forward only or bi-directional, inserts at the end only or any arbitrary position, more inserts or more reads, concurrently accessed or not, modification is allowed or not, homogeneous or heterogeneous collection, etc. Also, keep multi-threading, atomicity, memory usage and performance considerations discussed earlier in mind.

  • Don't assume that your collection is always going to be small as it can potentially grow bigger with time. So your collection should scale well.

  • Program in terms of interface not implementation: For example, you might decide a LinkedList is the best choice for some application, but then later decide ArrayList might be a better choice for performance reason.

         Bad:
                  ArrayList list = new ArrayList(100);

        Good:
                 // program to interface so that the implementation can change
                List list = new ArrayList(100);
                List list2 = new LinkedList(100);


  • Return zero length collections or arrays as opposed to returning a null in the context of the fetched list is actually empty. Returning a null instead of a zero length collection is more error prone, since the programmer writing the calling method might forget to handle a return value of null.

          List emptyList = Collections.emptyList( );
          Set emptySet = Collections.emptySet( );

  • Use generics for type safety, readability, and robustness.

  • Encapsulate collections: In general, collections are not immutable objects. So care should be taken not to unintentionally expose the collection fields to the caller. The caller may not perform any necessary validation.