Reverse the order of a Sentence in Java

Recently, in an interview, i was asked to reverse a sentence, i.e. given a String “THIS IS AN INTERVIEW” , reverse it to “INTERVIEW AN IS THIS” without using any advanced APIs of Java.

I had tried to solve the problem with the java.util.regex.Pattern class after realizing that usage of StringTokenizer is discouraged in the Java Docs. However,the solution was not accepted as it used Pattern class. So, i was determined to solve the problem myself and have come up with the below solution. Please provide your valuable feedback. The soultion here uses basic classes like String, StringBuilder and char. The solution here can be enhanced for a character-sequence. Currently, it works only for a single character.

import java.util.regex.Pattern;

public class TestStringSplitAndReversal {

    public static void main(String args[]) {
        String testString = "THIS IS A TEST";
        char regex = ' ';
        String[] reversedString = TestStringSplitAndReversal.split(regex, testString);
        int size = reversedString.length;
        //For String reversal
        for (int i = size - 1; i >= 0; i--) {
            if (reversedString[i] != null)
                System.out.println("Element:::" + reversedString[i]);
        }
    }

    // Regular Splitting using Java's API
    public static String[] split(String regex, String str) {
        return Pattern.compile(regex).split(str);
    }

    // Splitting without using any advanced APIs of Java
    public static String[] split(char regex, String str) {
        char[] actual = str.toCharArray();
        // char[] temp=new char[str.length()];
        StringBuilder tempStr = new StringBuilder();
        int j = 0, k = 0;
        String[] result = new String[str.length()];
        int resultSize = 1;
        for (int i = 0; i < actual.length; i++) {
            // temp[j++]=actual[i];
            tempStr = tempStr.append(actual[i]);
            if (regex == actual[i]) {
                result[k++] = new String(tempStr);
                // j=0;
                resultSize++;
                // temp=new char[str.length()];
                tempStr = new StringBuilder();
            }
        }
        // result[k++]=new String(temp);
        result[k++] = new String(tempStr);
        return resizeArray(result, resultSize);
    }

    //This resizing is required as once an Array is initialized to a size, 
    //it cannot be shrinked.Hence, we need to create a new Array.
    public static String[] resizeArray(String[] original, int resultCount) {
        String[] result = new String[resultCount];
        for (int i = 0; i < original.length; i++) {
            if (original[i] != null) {
                result[i] = original[i];
            }
        }
        return result;
    }

}

Difficult Servlet Interview Questions

a) How do you get the count of how many times the Servlet was accessed?
Ans: Use Filters and in the doFilter() method, mantain a counter which gets stored in the servletContext.

b) How do you get the no. of users who accessed your application?
Ans: Use HttpSessionListener and increment/decrement the userCount variable which gets stored in the servletContext on the sessionCreated() and sessionDestroyed() method.

c) What is the life cycle of ServletContextListener?
Ans: contextInitialized() and contextDestroyed()

d) What is the life cycle of Filter?
Ans: init, doFilter, destroy

e) What is the difference between Page and PageContext?(Courtesy:Suman)
Ans: page and pageContext are implicit variables.
page : page is of class java.lang.Object,and it refers to instance of generated servlet.It is declared as
Object page=this;
// this refers to the instance of this servlet page cannot be used to directly call the servlet methods.
Usages of Page:
1) Error bcoz page is Object type
2) <%=((servlet)page).getServletInfo()%> <—-OK:typecast
3) <%=this.getServletInfo()%> <——-OK

pageContext :
pageContext is of type javax.servlet.jsp.PageContext.
pageContext class is an abstract class.
Usages of PageContext:
1) provide convenience methods to get and set attributes in diff scopes.
2) provide convenience methods for transfering requests to other resources in the web application
void include(String relativeURL) & void forward(String relativeURL)
e.g. pageContext.forward(“suman.jsp”);
3)store the references to implicit objects

e) How do you ensure that a user session is closed , when actually the user has closed the browser window without logging out explicity?
Ans: In HttpSession, you have a method by the name getLastAccessedTime() which can be used to identify the in-active period and invalidate the session by calling session.inValidate()

f) What are the attributes of a ConnectionPool?
Ans: Click here

g) How do you download a file from a Servlet?
Ans: Click here

Implementing Producer and Consumer in Java

The code to implement a Producer and Consumer in Java is mentioned below, courtesy : cs.wellesley.edu.



import java.util.*;
import java.io.*;

// We would like to synchronize producer and consumer so that
// producer puts a number in the buffer, then the consumer takes it
// out, then the producer puts another number, and so on.

// This solution provides the right behaviour
// We have changed the class Buffer to include wait() and notify()
// We also have changed the producer and cinsumer classes
// slightly to handle a new exception

public class ConsumerProducerGood {

  public static void main (String [] args) {
    Buffer buf = new Buffer();
    
    // create new threads
    Thread prod = new Producer(10, buf);
    Thread cons = new Consumer(10, buf);
    
    // starting threads
    prod.start();
    cons.start();
    
    // Wait for the threads to finish
    try {
        prod.join();
        cons.join();
    } catch (InterruptedException e) {return;}
  }
 
} 

class Buffer {
          private int contents;
          private boolean empty = true;
          
          public synchronized void put (int i) throws InterruptedException { 
              while (empty == false) {     //wait till the buffer becomes empty
                  try { wait(); }
                  catch (InterruptedException e) {throw e;}
              }
              contents = i;
              empty = false;
              System.out.println("Producer: put..." + i);
              notify();
          } 
          
          public synchronized int get () throws InterruptedException {
              while (empty == true)  {    //wait till something appears in the buffer
                  try {     wait(); }
                  catch (InterruptedException e) {throw e;}
              }
              empty = true;
              notify();
              int val = contents;
              System.out.println("Consumer: got..." + val);
              return val;
          }
}


public class Producer extends Thread {
      private int n;
      private Buffer prodBuf;
      
      public Producer (int m, Buffer buf) {
          n = m;
          prodBuf = buf;
    }
    
    public void run() {
        for (int i = 0; i < n; i++) {
            try {
                Thread.sleep( (int) Math.random() * 100); // sleep for a randomly chosen time
            } catch (InterruptedException e) {return;}
            
            try {
                prodBuf.put(i + 1); //starting from 1, not 0
            } catch (InterruptedException e) {return;}
            
        }
    }
  }

public class Consumer extends Thread {
      private int n;
      private Buffer consBuf;
      
      public Consumer (int m, Buffer buf) {
          n = m;
          consBuf = buf;
    }
    
    public void run() {
        int value;
        for (int i = 0; i < n; i++) {
            try {
                value = consBuf.get();
            }  catch (InterruptedException e) {return;}
            try {
                Thread.sleep( (int) Math.random() * 100); // sleep for a randomly chosen time
            } catch (InterruptedException e) {return;}
            
        }
    }
  }





Implementing Connection Pool In Java

The code to implement a good connection pool is mentioned below, courtesy: Song Jing



import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;

/**
* A class for preallocating, recycling, and managing
* JDBC connections.
* <p/>
* © 2002 Song Jing; may be freely used or adapted.
*/

public class ConnectionPool implements Runnable
{
private String driver, url, username, password;
private int maxConnections;
private boolean waitIfBusy;
private Vector availableConnections, busyConnections;
private boolean connectionPending = false;

public ConnectionPool(String driver, String url,
String username, String password,
int initialConnections,
int maxConnections,
boolean waitIfBusy)
throws SQLException
{
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
this.maxConnections = maxConnections;
this.waitIfBusy = waitIfBusy;
if (initialConnections > maxConnections)
{
initialConnections = maxConnections;
}
availableConnections = new Vector(initialConnections);
busyConnections = new Vector();
for (int i = 0; i < initialConnections; i++)
{
availableConnections.addElement(makeNewConnection());
}
}

public synchronized Connection getConnection()
throws SQLException
{
if (!availableConnections.isEmpty())
{
Connection existingConnection=
(Connection) availableConnections.lastElement();
int lastIndex = availableConnections.size() - 1;
availableConnections.removeElementAt(lastIndex);
// If connection on available list is closed (e.g.,
// it timed out), then remove it from available list
// and repeat the process of obtaining a connection.
// Also wake up threads that were waiting for a
// connection because maxConnection limit was reached.
if (existingConnection.isClosed())
{
notifyAll(); // Freed up a spot for anybody waiting
return (getConnection());
}
else
{
busyConnections.addElement(existingConnection);
return (existingConnection);
}
}
else
{

// Three possible cases:
// 1) You haven't reached maxConnections limit. So
// establish one in the background if there isn't
// already one pending, then wait for
// the next available connection (whether or not
// it was the newly established one).
// 2) You reached maxConnections limit and waitIfBusy
// flag is false. Throw SQLException in such a case.
// 3) You reached maxConnections limit and waitIfBusy
// flag is true. Then do the same thing as in second
// part of step 1: wait for next available connection.

if ((totalConnections() < maxConnections) &&
!connectionPending)
{
makeBackgroundConnection();
}
else if (!waitIfBusy)
{
throw new SQLException("Connection limit reached");
}
// Wait for either a new connection to be established
// (if you called makeBackgroundConnection) or for
// an existing connection to be freed up.
try
{
wait();
}
catch (InterruptedException ie) {}
// Someone freed up a connection, so try again.
return (getConnection());
}
}

// You can't just make a new connection in the foreground
// when none are available, since this can take several
// seconds with a slow network connection. Instead,
// start a thread that establishes a new connection,
// then wait. You get woken up either when the new connection
// is established or if someone finishes with an existing
// connection.

private void makeBackgroundConnection()
{
connectionPending = true;
try
{
Thread connectThread = new Thread(this);
connectThread.start();
}
catch (OutOfMemoryError oome)
{
// Give up on new connection
}
}

public void run()
{
try
{
Connection connection = makeNewConnection();
synchronized(this)
{
availableConnections.addElement(connection);
connectionPending = false;
notifyAll();
}
}
catch (Exception e)
{ // SQLException or OutOfMemory
// Give up on new connection and wait for existing one
// to free up.
}
}

// This explicitly makes a new connection. Called in
// the foreground when initializing the ConnectionPool,
// and called in the background when running.

private Connection makeNewConnection()
throws SQLException
{
try
{
// Load database driver if not already loaded
Class.forName(driver);
// Establish network connection to database
Connection connection=
DriverManager.getConnection(url, username, password);
return (connection);
}
catch (ClassNotFoundException cnfe)
{
// Simplify try/catch blocks of people using this by
// throwing only one exception type.
throw new SQLException("Can't find class for driver: " +
driver);
}
}

public synchronized void free(Connection connection)
{
busyConnections.removeElement(connection);
availableConnections.addElement(connection);
// Wake up threads that are waiting for a connection
notifyAll();
}

public synchronized int totalConnections()
{
return (availableConnections.size() +
busyConnections.size());
}

/**
* Close all the connections. Use with caution:
* be sure no connections are in use before
* calling. Note that you are not <I>required to
* call this when done with a ConnectionPool, since
* connections are guaranteed to be closed when
* garbage collected. But this method gives more control
* regarding when the connections are closed.
*/

public synchronized void closeAllConnections()
{
closeConnections(availableConnections);
availableConnections = new Vector();
closeConnections(busyConnections);
busyConnections = new Vector();
}

private void closeConnections(Vector connections)
{
try
{
for (int i = 0; i < connections.size(); i++)
{
Connection connection=
(Connection) connections.elementAt(i);
if (!connection.isClosed())
{
connection.close();
}
}
}
catch (SQLException sqle)
{
// Ignore errors; garbage collect anyhow
}
}

public synchronized String toString()
{
String info=
"ConnectionPool(" + url + "," + username + ")" +
", available=" + availableConnections.size() +
", busy=" + busyConnections.size() +
", max=" + maxConnections;
return (info);
}
}