Comparable vs Comparator

There are many articles available on internet for this. But still I would write something about it.

What when and why?

A Comparable class is a class, which can be compared with the objects of its own type. Let us take an example of a book.

public class Book implements Comparable {
    String title;
    int    isbn;

    Book(String title, int isbn) {
        this.title = title;
        this.isbn  = isbn;
    /* This method will be the default method used 
       to sort Book objects in a list or Array */
    public int compareTo(Object object) {
    // It should throw NullPointerException if object passed is null
    if (object==null)
        throw new NullPointerException("compareTo: Argument passed is null");
        Book other = (Book) object;
        if (this.title.equals(other.title)) {
            return this.isbn - other.isbn;
        return this.title.compareTo(other.title);

The moment your class implements Comparable, you can then use

List list = new LinkedList();
        list.add(new Book("Patterns", 12345));
        list.add(new Book("Apples", 34567));
        list.add(new Book("Examples", 23456));


Using this you can sort your list.

But what if now, you want to add or use another sorting criteria defined in Book class… Here comes the need of Comparator.
There are two ways listed here to use the Comparator class.

First method

We create a anonymous class that implements Comparator and overrides compare method.

Collections.sort(list, new Comparator() {
            public int compare(Object obj1, Object obj2) {
                if(obj1 == null || obj2 == null){
                    throw new NullPointerException("compareTo: Argument passed is null");
                Book book1 = (Book) obj1;
                Book book2 = (Book) obj2;
                return book1.isbn - book2.isbn;


Second Method

You define a class that implements Comparator like as below.

class BookComparator implements Comparator{
    public int compare(Object book1, Object book2){
        int b1= ((Book)book1).isbn;        
        int b2= ((Book)book2).isbn;
        if(b1> b2)
            return 1;
        else if(b1< b2)
            return -1;
            return 0;    

And use this newly defined comparator class as an argument to Collections.sort.

Arrays.sort(list, new BookComparator ());

Good reasons to use Comparator interface

  • I do not have permissions to edit the Book class.
  • Book class already implements Comparable interface, but I want to sort the objects using a different criteria
  • I want to have more than 1 criterias to sort the objects in different orders.

Reasons to implement Comparable interface

  • I want my class to have a default sorting criteria that can be used by the users of my class
  • Usually, one would like to sort the objects based on primary key

Few good links on this topic are here

The absolute uri: cannot be resolved in either web.xml or the jar files deployed with this application

The jsp page gives the following error : The absolute uri: cannot be resolved in either web.xml or the jar files deployed with this application

Even if you include this:

in your jsp page, it still gives the error.

The reason is that it depends upon the web app version. The web app version is defined in the web.xml file as follows:

Here’s an example of what to look for in web.xml:

id="WebApp_ID" version="2.5">

You can see the version=”2.5″ designation in here. This means that within this web application, we will be able to use JSP 2.1 and JSTL 1.2 features.

Here, the web app version is 2.3.

So, if you are using web app version 2.3, then we should use :

For Web app versions 2.4 & 2.5, you should use:

Complete Error Trace:

WARNING: /SpringDemo/customer.htm:
org.apache.jasper.JasperException: The absolute uri: cannot be resolved in either web.xml or the jar files deployed with this application
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(
at org.apache.jasper.compiler.ErrorDispatcher.dispatch(
at org.apache.jasper.compiler.ErrorDispatcher.jspError(
at org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(
at org.apache.jasper.compiler.TagLibraryInfoImpl.(
at org.apache.jasper.compiler.Parser.parseTaglibDirective(
at org.apache.jasper.compiler.Parser.parseDirective(
at org.apache.jasper.compiler.Parser.parseElements(
at org.apache.jasper.compiler.Parser.parse(
at org.apache.jasper.compiler.ParserController.doParse(
at org.apache.jasper.compiler.ParserController.parse(
at org.apache.jasper.compiler.Compiler.generateJava(
at org.apache.jasper.compiler.Compiler.compile(
at org.apache.jasper.compiler.Compiler.compile(
at org.apache.jasper.compiler.Compiler.compile(
at org.apache.jasper.JspCompilationContext.compile(
at org.apache.jasper.servlet.JspServletWrapper.service(
at org.apache.jasper.servlet.JspServlet.serviceJspFile(
at org.apache.jasper.servlet.JspServlet.service(
at javax.servlet.http.HttpServlet.service(
at org.mortbay.jetty.servlet.ServletHolder.handle(
at org.mortbay.jetty.servlet.WebApplicationHandler.dispatch(
at org.mortbay.jetty.servlet.Dispatcher.dispatch(
at org.mortbay.jetty.servlet.Dispatcher.forward(
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(
at org.springframework.web.servlet.view.AbstractView.render(
at org.springframework.web.servlet.DispatcherServlet.render(
at org.springframework.web.servlet.DispatcherServlet.doDispatch(
at org.springframework.web.servlet.DispatcherServlet.doService(
at org.springframework.web.servlet.FrameworkServlet.processRequest(
at org.springframework.web.servlet.FrameworkServlet.doPost(
at javax.servlet.http.HttpServlet.service(
at javax.servlet.http.HttpServlet.service(
at org.mortbay.jetty.servlet.ServletHolder.handle(
at org.mortbay.jetty.servlet.WebApplicationHandler.dispatch(
at org.mortbay.jetty.servlet.ServletHandler.handle(
at org.mortbay.http.HttpContext.handle(
at org.mortbay.jetty.servlet.WebApplicationContext.handle(
at org.mortbay.http.HttpContext.handle(
at org.mortbay.http.HttpServer.service(
at org.mortbay.http.HttpConnection.service(
at org.mortbay.http.HttpConnection.handleNext(
at org.mortbay.http.HttpConnection.handle(
at org.mortbay.http.SocketListener.handleConnection(
at org.mortbay.util.ThreadedServer.handle(
at org.mortbay.util.ThreadPool$

Reference :

java.lang.UnsupportedClassVersionError: Bad version number in .class file

java.lang.UnsupportedClassVersionError: Bad version number in .class file

[at java.lang.ClassLoader.defineClass1(Native Method)]

is an error that you may face in running a compiled java class file.

So as you can see from the stack trace, a class has not been loaded. But which class?

The problem is this error message does not show the name of the failed .class, isn’t it?

No, it is not. This error is caused when you compile a .java file with one version of JDK and running the .class file with a different version of JVM.

Confused? You may say; same version is not required to compile and run.

Yes, that is true. But you can not run .class files that are compiled with a newer version than the JVM.


javac (compile) - version: X
java (run) - version: Y

If X is newer than Y; then you may face this issue at runtime.

Reference :

Here is the supporting example.

Set the path to 1.6 for compilation

C:UsersYogiDesktop>set PATH=”C:Program FilesJavajdk1.6.0_10bin”;%PATH%


Now run the class using 1.5 jre

C:UsersYogiDesktop>set PATH=”C:Program FilesJavajre1.5.0_06bin”;%PATH%

C:UsersYogiDesktop>java test
Exception in thread “main” java.lang.UnsupportedClassVersionError: Bad version n
umber in .class file
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at Source)
at Source)
at$100(Unknown Source)
at$ Source)
at Method)
at Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)

Common Mistakes in Collections

Source :

Classes like Integer, String, Double etc implements Comparable interface. So if we are to use an object of a custom class as the key, ensure that it’ s class implements the Comparable interface.

public class MyCustomKey implements Comparable
    private int value;
    public MyCustomKey(int value)
       this.value = value;

    public int compareTo (MyCustomKey key)
       int comparison = 0;           

       // Note:
       // Return -1 if this.value < key.value
       // Return  0 if this.value = key.value
       // Return  1 if this.value > key.value           

       return (comparison);

A common mistake that everyone does is not to override the hashcode(). If we are failing to do so, map.get(new MyCustomKey()); may not give you what you were expecting. So it is always advised to override the hashCode() if objects of that class is being used as a key.

public class MyCustomKey implements Comparable
    private int value;
    public MyCustomKey(int value)
    public int compareTo (MyCustomKey key)

    public int hashCode()
        // Note:
        // If two objects are equal then their corresponding hashCode ()
        // should return the same value too.
        return (this.value * 199);

When you are using your custom object as a key to a HashMap, make sure you do the following

1) implement Comparable
2) override compareTo method, and give its implementation
3) override hashCode and equals method, and give their implementation.
4) Always, make your key object as immutable, so that it is not changed after you add it to a HashMap as key.

How to use logger in your Java application

How to log Messages in your application?

Java’s logging facility has two parts: a configuration file, and an API for using logging services. It is suitable for simple and moderate logging needs. Log entries can be sent to the following destinations, as either simple text or as XML:
· The console
· A file
· A stream
· Memory
· TCP socket on a remote host

The LEVEL class defines seven levels of logging enlightenment :
FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE .ALL and OFF are defined values as well

The levels in code may be modified as required :
· Upon startup, by using CONFIG to log configuration parameters
· During normal operation, by using INFO to log high-level “heartbeat” information
· When bugs or critical conditions occur, by using SEVERE.
· Debugging information might default to FINE, with FINER and FINEST used occasionally, according to user need.

There is flexibility in how logging levels can be changed at runtime, without the need for a restart:
· By simply changing the configuration file and calling LogManager.readConfiguration.
· By changing the level in the body of code , using the logging API ;
For example, one might automatically increase the logging level in response to unexpected events

The logging levels are in descending order SEVERE, WARNING, INFO, CONFIG, FINE, FINER and FINEST. If we specify log level as

INFO then all the log messages which are equal to INFO and greater (WARNING, SEVERE) levels will be logged.

Levels are attached to the following items:
· An originating logging request (from a single line of code)
· A Logger (usually attached to the package containing the above line of code)
· A Handler (attached to an application)

Here is an example of a logging configuration file :

Properties file which configures the operation of the JDK

logging facility. # The system will look for this config file, first using

a System property specified at startup:

>java -Djava.util.logging.config.file=myLoggingConfigFilePath

If this property is not specified, then the config file is retrieved

from its default location at:


Global logging properties.


The set of handlers to be loaded upon startup.

Comma-separated list of class names.

(? LogManager docs say no comma here, but JDK example has comma.)

handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler

Default global logging level.

Loggers and Handlers may override this level




Loggers are usually attached to packages.

Here, the level for each package is specified.

The global level is used by default, so levels

specified here simply act as an override.




— ConsoleHandler —

Override of global logging level


— FileHandler —

Override of global logging level


Naming style for the output file:

(The output file is placed in the directory

defined by the “user.home” System property.)


Limiting size of output file in bytes:


Number of output files to cycle through, by appending an

integer to the base file name:


Style of output (Simple or XML):


Here is an example of using the logging API :

import java.util.logging.*;
* Demonstrate Java's logging facilities, in conjunction
* with a logging config file.
public final class SimpleLogger {

  public static void main(String argv[]) {
    SimpleLogger thing = new SimpleLogger();
   public void doSomething() {
   //Log messages, one for each level
   //The actual logging output depends on the configured
    //level for this package. Calls to "inapplicable"
    //messages are inexpensive.
     fLogger.finest("this is finest");
    fLogger.finer("this is finer");
    fLogger.fine("this is fine");
    fLogger.config("this is config");"this is info");
    fLogger.warning("this is a warning");
    fLogger.severe("this is severe");

    //In the above style, the name of the class and
    //method which has generated a message is placed
    //in the output on a best-efforts basis only.
    //To ensure that this information is always
    //included, use the following "precise log"
    //style instead :
    fLogger.logp(Level.INFO, this.getClass().toString(), "doSomething", "blah");

    //For the very common task of logging exceptions, there is a
    //method which takes a Throwable :
    Throwable ex = new IllegalArgumentException("Some exception text");
    fLogger.log(Level.SEVERE, "Some message", ex);

    //There are convenience methods for exiting and
    //entering a method, which are at Level.FINER :
    fLogger.exiting(this.getClass().toString(), "doSomething");

    //Display user.home directory, if desired.
    //(This is the directory where the log files are generated.)
    //System.out.println("user.home dir: " + System.getProperty("user.home") );

  // PRIVATE //

  //This logger will inherit the config of its parent, and add
  //any further config as an override. A simple style is to use
  //all config of the parent except, perhaps, for logging level.

  //This style uses a hard-coded literal and should likely be avoided:
  //private static final Logger fLogger = Logger.getLogger("");

  //This style has no hard-coded literals, but forces the logger
  //to be non-static.
  //private final Logger fLogger=Logger.getLogger(this.getClass().getPackage().getName());

  //This style uses a static field, but hard-codes a class literal.
  //This is probably acceptable.
  private static final Logger fLogger = Logger.getLogger(SimpleLogger.class.getPackage().getName());


How to read a file in Java

Usually such kind of function is not recommended when reading huge files. Because it is not possible for java to allocate so much contiguous memory.

As far a possible, avoid using this function.

public static String getFile(String filepath) 
        StringBuilder output = new StringBuilder("");
            File file = new File(filepath);
            FileReader fileReader = new FileReader(file);
            BufferedReader bfr = new BufferedReader(fileReader);
            String line ;
            while((line = bfr.readLine()) != null)
                output.append(line + "n");
        catch (FileNotFoundException e) 
        catch (IOException e) 
        return output.toString();