Monday, August 29, 2011

LinkedHashMap and IdentityHashMap


A LinkedHashMap is a combination of hash table and linked list. It has a predictable iteration order (a la linked list), yet the retrieval speed is that of a HashMap. The order of the iteration is determined by the insertion order.

We have a requirment say want to retrieve rows from a database table and convert these rows to Java Objects. Let us also imagine we are not using JDO. We need the elements in some order, and we need to search on keys quickly.

Before JDK 1.4, I would probably have made the objects Comparable and inserted them into a TreeMap. TreeMap works with a type of balanced binary tree, so the lookup would be O(log2n). If we have 1024 elements, it will take at most ten lookups. This is worse than a HashMap with a good hash function, which should only take one lookup. Keeping the tree balanced is expensive since it involves shuffling the nodes around whenever one side of the tree becomes too deep. Inserting the elements into a TreeMap is probably more expensive than sorting in your database, since the database is optimised for such things.

With the LinkedHashMap we get the best of both worlds. We can let the database do the sorting, retrieve the rows and insert them into the LinkedHashMap. This way we can retrieve them quickly via the HashMap mechanism, but we can still iterate through them in the sorted order.

To illustrate
Student class with roll number, name and DOB.
package LinkedHashMapTest;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Student {
private final String id;
private final String name;
private final Date dateofbirth;
public Student(String id, String name, Date dateofbrith)
{      
               this.name = name;
this.id = id;
this.dateofbirth = dateofbrith;
}
private final static DateFormat df = 
   new SimpleDateFormat("yyyy/MM/dd");
 public String toString() {
   return name + " born on " + df.format(dateofbirth);
 }
public String getId() {
return id;
}
public String getName() {
return name;
}
public Date getDateofbirth() {
return dateofbirth;
}
public int hashCode(){
return id.hashCode();
}
public boolean equals(Object obj)
{
if(!(obj instanceof String))  return false;
String key = (String)obj;
return id.equals(key);
}
}


Now define Interface Department.
public interface Department
{
   Student[] getStudents();
}

Define ComputerScient Department with students
import java.util.Date;

public class ComputerScienceDepartment implements Department {
private final static Student[] students = {
new Student("19", "Keerthi", new Date(88, 11, 25)),
new Student("01", "Kanish", new Date(99, 07, 27)),
new Student("22", "Naresh", new Date(81, 02, 07)),
new Student("11", "Avi", new Date(82, 05, 07)),
new Student("44", "Vedh", new Date(84, 03, 10)),
new Student(new String("44"), "Vedh", new Date(84, 03, 10)),
};

@Override
public Student[] getStudents() {
return students;
}
}

Note that the students are sorted by name. We assume that the students would be retrieved in that sort order from the database. We can see the difference between the HashMaps from this example: 

IdentityHashMap as name suggests uses the equality operator(==) for comparing the keys. So when you put any Key Value pair in it the Key Object is compared using == operator

import java.util.*;
public class LinkedHashMapTest {
  private static void fill(Map players, Department sd) {
    Student[] p = sd.getStudents();
    for (int i = 0; i < p.length; i++) {
      players.put(p[i].getId(), p[i]);
    }
  }  
  private static void test(Map players, Department sd) {
    System.out.println("Testing " + players.getClass().getName());
    fill(players, sd);
    for (Iterator it = players.values().iterator(); it.hasNext();) {
      System.out.println(it.next());
    }
    System.out.println();
  }  
  public static void main(String[] args) {
    Department sd = new ComputerScienceDepartment();
    test(new HashMap(), sd);
    test(new LinkedHashMap(), sd);
    test(new IdentityHashMap(), sd);
  }
}



When we run this code, we get the following output:
Testing java.util.HashMap
Vedh born on 1984/04/10
Hanuman born on 1988/12/25
Naresh born on 1981/03/07
Kanish born on 1999/08/27
Sairam born on 1982/06/07

Testing java.util.LinkedHashMap
Hanuman born on 1988/12/25
Kanish born on 1999/08/27
Naresh born on 1981/03/07
Sairam born on 1982/06/07
Vedh born on 1984/04/10

Testing java.util.IdentityHashMap
Hanuman born on 1988/12/25
Kanish born on 1999/08/27
Vedh born on 1984/04/10
Sairam born on 1982/06/07
Naresh born on 1981/03/07
Vedh born on 1984/04/10

LRU Cache
Another application for the LinkedHashMap is in building LRU caches. One of the constructors allows us to specify that we use access order instead of insert order. The order is from least-recently accessed to most-recently. You can override the removeEldestEntry(Map.Entry) method to impose a policy for automatically removing stale when new mappings are added to the map.



Thursday, April 14, 2011

JAXB basic example

JAXB - Java to xml binding and vice versa.

This blog is helpful for those who are new to jaxb. It just helps you to start.

1) Create java classes from xsd(if you dont have xsd use trang to generate one.). To create java classes we can use xjc.
2) Annotated java classes will be created.
3) compile the java classes.
3) Modify java classes and write marshall(Java -> xml) code inside the main method of the class.
4) Now you will get xml from the java object as part of marshalling.
for unmarshalling( xml --> Java) modify code at step3 with unmarshalling code and run the java class.
See below code for more information.

Here I am giving simple startup example on windows.

1) Download the binary and execute the jar
http://jaxb.java.net/2.2.3u2/
> java -jar JAXB2_20110412.jar
After running above command you will get a folder with name "jaxb-ri-20101209"

2) set windows classpath to C:\jaxb-ri-20101209\bin. This is to get xjc on classpath. xjc is used to generate java classes from xml.

3) Use Employee.xsd as shown below
 <?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="employee">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="firstName"/>
        <xs:element ref="middleName"/>
        <xs:element ref="lastName"/>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:integer"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="firstName" type="xs:NCName"/>
  <xs:element name="middleName" type="xs:NCName"/>
  <xs:element name="lastName" type="xs:NCName"/>
</xs:schema>

4) run below command to genreate java classes from the xsd
     xjc Employee.xsd

5) Below Java Class will be generated
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "firstName",
    "middleName",
    "lastName"
})
@XmlRootElement(name = "employee")
public class Employee {
    @XmlElement(required = true)
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    @XmlSchemaType(name = "NCName")
    protected String firstName;
    @XmlElement(required = true)
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    @XmlSchemaType(name = "NCName")
    protected String middleName;
    @XmlElement(required = true)
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    @XmlSchemaType(name = "NCName")
    protected String lastName;
    @XmlAttribute(name = "id", required = true)
    protected int id;
    /**
     * Gets the value of the firstName property.        
     */
    public String getFirstName() {
        return firstName;
    }
    /**
     * Sets the value of the firstName property.        
     */
    public void setFirstName(String value) {
        this.firstName = value;
    }
    /**
     * Gets the value of the middleName property.       
     */
    public String getMiddleName() {
        return middleName;
    }
    /**
     * Sets the value of the middleName property.    
     */
    public void setMiddleName(String value) {
        this.middleName = value;
    }
    /**
     * Gets the value of the lastName property.    
     */
    public String getLastName() {
        return lastName;
    }
    /**
     * Sets the value of the lastName property.        
     */
    public void setLastName(String value) {
        this.lastName = value;
    }
    /**
     * Gets the value of the id property.        
     */
    public int getId() {
        return id;
    }
    /**
     * Sets the value of the id property.     
     */
    public void setId(int value) {
        this.id = value;
    }
}
 
6) Add below jars to the project build path in the eclipse.
activation-1.1.jar
jaxb-api-2.0.jar
jaxb-impl-2.0.5.jar
jsr173_api-1.0.jar
jaxb-xjc.jar


7) Now modify your java class by adding main method for marshalling  i.e. java to xml.
public static void main(String args[]) throws JAXBException{
     Employee greg = new Employee();
     greg.setId(1);
     greg.setFirstName("Greg");   
     greg.setMiddleName("");
     greg.setLastName("Loyd");
   
     //java object to xml converstion    MARSHALLING
     JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
     StringWriter stringWriter = new StringWriter();
     jaxbContext.createMarshaller().marshal(greg, stringWriter);   
     System.out.println("....Marshalling....."+  stringWriter.toString());
}

8) compile above java class. You will get xml in a string fromat.

9) Modify same java class for unmarshalling.


public static void main(String args[]) throws JAXBException{
Employee greg = new Employee();
greg.setId(1);
greg.setFirstName("Greg");
greg.setMiddleName("");
greg.setLastName("Loyd");
//java object to xml converstion MARSHALLING
JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
StringWriter stringWriter = new StringWriter();
jaxbContext.createMarshaller().marshal(greg, stringWriter);
System.out.println("....Marshalling....."+ stringWriter.toString());
//End stringWriter is an xml
//xml to java object
Employee gregUnmarshal = (Employee)jaxbContext.createUnmarshaller().unmarshal(new StringReader(stringWriter.toString()));
if(greg.equals(gregUnmarshal)){
   System.out.println("....marshal and unmarshal objects are same");
}else{
   System.out.println("....marshal and unmarshal objects are not same");
}
}
package generated;

10) Run the java class and you get output for both marshalling and unmarshalling.
....Marshalling.....<?xml version="1.0" encoding="UTF-8" standalone="yes"?><employee id="1"><firstName>Greg</firstName><middleName></middleName><lastName>Loyd</lastName></employee>
....marshal and unmarshal objects are same

Saturday, February 5, 2011

Find loop in a linked list

 



We have to maintain two pointers one slow pointer that moves one node at a time and a fast pointer that moves two nodes at  a time.



#include <stdio.h>
#include <stdlib.h>

struct linkedList{
    int number;
    struct linkedList* next;
};

typedef struct linkedList* NODE;

int FindLoop(NODE *head)
{
    NODE *fastPtr, *slowPtr;
    fastPtr = slowPtr = head;
    while(1)
    {
        if(!fastPtr || !fastPtr->next)
            return 0;
        else if(fastPtr == slowPtr || fastPtr ->next == slowPtr)
            return 1; // Loop Exist
        else{
            slowPtr = slowPtr->next;
            fastPtr = fastPtr->next->next;
        }
    }
    return 0;
}