Showing posts with label Collections. Show all posts
Showing posts with label Collections. Show all posts

Monday, October 3, 2011

Making collections final

Once we write final
ArrayList list = new ArrayList();

We can add, delete objects from this list, but I can not
list = new ArrayList() or list = list1.

So declaring the list final means that you cannot reassign the list variable to another object.

There are two situations in which this can be useful.
  1. You want to make sure that no-one reassigns your list variable once it has received its value. This can reduce complexity and helps in understanding the semantics of your class/method. In this case you are usually better off by using good naming conventions and reducing method length (the class/method is already too complex to be easily understood).
  2. When using inner classes you need to declare variables as final in an enclosing scope so that you can access them in the inner class. This way, Java can copy your final variable into the inner class object (it will never change its value) and the inner class object does not need to worry what happens to the outer class object while the inner class object is alive and needs to access the value of that variable.


Thursday, July 7, 2011

Deque in java

The java.util.Deque interface is a subtype of the java.util.Queue interface. It represents a queue where you can insert and remove elements from both ends of the queue. Thus, "Deque" is short for "Double Ended Queue" and is pronounced "deck", like a deck of cards.

Deque Implementations

Being a Queue subtype all methods in the Queue and Collection interfaces are also available in the Deque interface.

Since Deque is an interface you need to instantiate a concrete implementation of the interface in order to use it. You can choose between the following Deque implementations in the Java Collections API:


LinkedList is a pretty standard Deque / Queue implementation.

Internal Implementation
ArrayDeque stores its elements internally in an array. If the number of elements exceeds the space in the array, a new array is allocated, and all elements moved over. In other words, the ArrayDeque grows as needed, even if it stores its elements in an array.

Possible Usage
Because the double-ended queue supports addition or removal of elements from either end of the data structure, it can be used as a queue (first-in-first-out/FIFO) or as a stack (last-in-first-out/LIFO). J2SE 5 introduced a Queue interface and the Deque interface extends this interface. Note that a Vector-based Stack class has been present since JDK 1.0, but 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 as well.

The Deque interface is extended by the concurrency-supporting interface BlockingDeque and is implemented by classes LinkedBlockingDeque (introduced in Java SE 6), LinkedList (available since JDK 1.2, but now implements Deque), and ArrayDeque (introduced in Java SE 6). For this blog entry, I will demonstrate using one Deque instance as a queue and one Deque instance as a stack using ArrayDeque for both. ArrayDeque is not thread-safe and does not allow for elements of the data structure to be null (a recommended but not required condition of Deque implementations and uses).

Operations on Deque
Adding to deque
To add elements to the tail of a Deque you call its add() method. You can also use the addFirst() and addLast() methods, which add elements to the head and tail of the deque.
Deque dequeA = new LinkedList();

dequeA.add     ("element 1"); //add element at tail
dequeA.addFirst("element 2"); //add element at head
dequeA.addLast ("element 3"); //add element at tail

Getting or Peeking the element
You can peek at the element at the head of the queue without taking the element out of the queue. This is done via the element() method. You can also use the getFirst and getLast() methods, which return the first and last element in the Deque. Here is how that looks:
Object firstElement = dequeA.element();
Object firstElement = dequeA.getFirst();
Object lastElement  = dequeA.getLast();

Removing the element
To remove elements from a deque, you call the remove(), removeFirst() and removeLast methods. Here are a few examples:
Object firstElement = dequeA.remove();
Object firstElement = dequeA.removeFirst();
Object lastElement  = dequeA.removeLast();

Iterating over the elements
One method is normal foreach style:
//access via new for-loop
for(Object object : dequeA) {
    String element = (String) object;
}

Another method is via iterator
//access via Iterator
Iterator iterator = dequeA.iterator();
while(iterator.hasNext(){
  String element = (String) iterator.next();
}


Friday, June 24, 2011

Converting a Collection to an array

If you have been using Collections in Java 5 you probably have stumbled upon a problem of converting a given Collection<T> into an array of type T. In the Collection interface, there is a method called toArray() which returns an array of type Object[]. But then, if since Java 5 Collections are using generics, shouldn’t it be possible to get an array T[] of the generic type we used in the declaration of our Collection<T>? Well, there is a method T[] toArray(T[] a). But what is that strange “T[] a” doing there? Why is there no simple method T[] toArray() without any strange parameters? It seams like it shouldn’t be a big problem to implement such a method… but actually it is not possible to do so in Java 5, and we will show here why.
Let’s start from trying to implement that method by ourselves. As an example, we will extend the ArrayList class and implement there a method T[] toArrayT(). The method simply uses the standard Object[] toArray() method and casts the result to T[].

import java.util.*;

/**
 * Implementation of the List interface with "T[] toArrayT()" method.
 * In a normal situation you should never extend ArrayList like this !
 * We are doing it here only for the sake of simplicity.
 * @param <T> Type of stored data
 */
class HasToArrayT<T> extends ArrayList<T> {
    public T[] toArrayT() {
        return (T[]) toArray();
    }
}

public class Main {
    public static void main(String[] args) {
        // We create an instance of our class and add an Integer
        HasToArrayT<Integer> list = new HasToArrayT<Integer>();
        list.add(new Integer(4));

        // We have no problems using the Object[] toArray method
        Object[] array = list.toArray();
        System.out.println(array[0]);

        // Here we try to use our new method... but fail on runtime
        Integer[] arrayT = list.toArrayT(); // Exception is thrown :
        // "Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer"
        System.out.println(arrayT[0]);
    }
}

If you compile it and run, it will throw an exception when trying to use our new method. But why? Didn’t we do everything right? Objects stored in the array ARE Integers and toArray method returns an array of those objects, so what is the problem?

Java compiler gives us a hint to understand what is wrong. During compilation, you should see a warning at line 12, saying something like “Type safety: Unchecked cast from Object[] to T[]“. Let’s follow this trace and check if the array that comes out of our toArrayT method is really of type Integer[]. Put this code somewhere in main() method before the Integer[] arrayT = list.toArrayT() line :

System.out.println("toArrayT() returns Integer[] : "
    + (list.toArrayT() instanceof Integer[]));

When you run the program, you should get “false”, which means that toArrayT() DID NOT return Integer[]. Why? Well, many of you probably know the answer – it is Type Erasure. Basically, during compilation the compiler removes every information about the generic types. Effectively, when the program runs, all the appearances of T in our HasToArrayT class are nothing more than simple Object’s. It means, that the cast in the function toArrayT does not cast to Integer[] any more, even if we are using Integer in the declaration of the generic type. Actually, there is also a second problem here, coming from the way Java handles casting of arrays. This time however we would like to concentrate just on the first one – usage of generics.
So, if the information that T is an Integer is no longer there at runtime, is there any way to really return an array of type Integer[] ? Yes, there is, and it is exactly what the method T[] toArray(T[] a) in the Collections framework is doing. But the price you have to pay for it is the additional argument a, whose instance you have to create first by yourself. How do they use it there? Let’s look at how it is really implemented in, for example, ArrayList :

public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

As it is explained in the method’s Javadoc, if the specified array a is big enough it just copies elements into this array. If not, it creates a new array. What is important for us, is that when creating a new array it uses Arrays.copyOf method, specifying there a.getClass() as the type of array to create. So that’s where it needs that additional argument – to know what type of array to create. But then you might say, would it not be easier to fit there T.class instead of a.getClass()? No. Because of type erasure, T is no longer the type we specified. Moreover, we would get a compile time error if we wrote T.class! Some of you may be thinking about creating a new array the simple way – new T[], but it is also not possible because of the same reason. We have already discussed how to get Generic Arrays in Java here.
To put it straight, in order to return a new array of T, the type that we really specified, we MUST give something of that type to the function toArray. There is no other way the function could now what type of array it should create, because the generic type T supplied when creating that Collection is erased every time during compilation.
One other way to implement such a method is by using the Class<T[]> type as an input parameter. This way, instead of having to create a new instance a of array T[] and then using it in the function toArray(a), we could use the .class field – toArrayT(TYPE[].class) :

public T[] toArrayT(Class<T[]> c) {
        return (T[]) Arrays.copyOf(toArray(), size(), c);
 }

It still takes an argument, but it has two advantages over the T[] toArray(T[] a) function. First, it does not require you to create an instance of an array just to pass it to the function. Second, it is simpler. Of course, it has still the disadvantage of having to pass some argument.

After all, there is no perfect way to perform such a conversion. The best solution would be not to use arrays at all. Code with arrays is difficult to maintain and invites people to make mistakes that often come out not earlier than on runtime. Using collections is generally much preferred and if you use them all the time, you will not be forced to deal with the toArray method.

Thursday, June 23, 2011

Type Safety: why would you need a Collections.checkedSet in JDK1.4?

In one of the first posts on this blog I have discussed the problem of type checking (or lack of it) in some of Java collections even when using generics. Today I want to show you a similar issue that can break the type safety in your code. It’s a problem that can cause a really nasty bugs in your application – the ones that manifest themselves many thousand lines of code after the faulty method introduce it.
Imagine that you work with generics, but you use a third party code. What if some part of that code was written in Java 1.4 or earlier, therefore not using generics. Let’s go one step further: what if (for some reason) this code does not respect the typing of your collections? You would expect to get an error, right? Well, you’ll get one… but do you know when? Check the following code:

public static void main(String[] args) {
    // create a type-safe set of Integers and add some values to it
    Set<Integer> setOfInts = new HashSet<Integer>();
    setOfInts.add(new Integer(7));
    setOfInts.add(new Integer(13));

    // pass your set to a non-generic code
    Set uncheckedSet = setOfInts;
    // non-generic code does not respect your typing
    // and adds a String to your set of integers
    uncheckedSet.add(new String("Illegal"));

    // back in your code - do some set manipulations:
    System.out.println(setOfInts);
    setOfInts.remove(new Integer(7));

    // at the end iterate trough your set
    for (Integer integer : setOfInts) {
        System.out.println(integer);
    }
}

The code above is a simplified version of the described scenario. In lines 8 – 11 the ‘third party’ code is executed and adds a String into a set of Integers. So back to the question: in a given example when will error occur? One might assume in line 11 as the bad element is inserted… wrong! Maybe when we access the collection and print all of its elements?… wrong! We can even do some manipulations on it (line 15) and still be fine! The error will show his ugly head finally in the loop in line 18 when we will enter it for the second time. This will happen so late because in line 18 for the first time we access the inserted String and cast it to Integer – at this point ClassCastException occurs.
In the example above the distance between the faulty insertion and the place where exception is thrown is only seven lines, but you can imagine its being 7000. Your code can be working fine for 7000 hours and after that throw an exception that will basically give you no hint what’s wrong. If you do not use third party code you should not feel safe because of that – I am sure that if your project has more than 10000 lines there is a part of it so old and dusty that it was written without the usage of generics…
What can be done? Well, we are in luck as there is a quite simple way of protecting yourself from that: in java.util.Collections you will find a way to wrap your Set, Map or List into an forwarding class that will check in runtime the typing of the inserted objects. In the case of our code snippet we only need to add one line:

public static void main(String[] args) {
    // create a type-safe set of Integers and add some values to it
    Set<Integer> setOfInts = new HashSe<Integer>();
    setOfInts = Collections.checkedSet(setOfInts, Integer.class);
    setOfInts.add(new Integer(7));
    setOfInts.add(new Integer(13));

    // pass your set to a non-generic code
    Set uncheckedSet = setOfInts;
    // non-generic code does not respect your typing
    // and adds a String to your set of integers
    uncheckedSet.add(new String("Illegal"));

    // back in your code - do some set manipulations:
    System.out.println(setOfInts);
    setOfInts.remove(new Integer(7));

    // at the end iterate trough your set
    for (Integer integer : setOfInts) {
        System.out.println(integer);
    }
}

As you see the only difference between this and previous snippet is additional line (#4) in which we wrap our set of integers into a CheckedSet. See that due to Generic type erasure in Java the Collections.checked* methods require a class object besides a collection to wrap. Now when we run the new code the error will manifest itself just at the moment where an error is commited: in line 12 when we try to insert a string. Exactly what we needed!

To summarize: if in your project you use either third party code or legacy code that you suspect of not using generics consider wrapping your collections with Collection.checked* methods!


Note :
Users with jdk 6 or higher will get ClassCastException in any case, if they add some wrong datatype.

Type safety in Java Set and Map in JDK 1.4

Probably many of you still remember the lack of type checking in Java 1.4 Collections and how much hassle it was to deal with casting the collection elements, not to mention how many errors this introduced to the code. Since introduction of generics in Java 1.5 this have really improved and one might think that nowadays the language itself protects the programmer from the silliest of typing mistakes. Generics themselves brought with them a set of new complications, but it seems reasonable to think that in the basic code situations when using Java’s Sets or Maps and when there is no kung-fu complications like wildcards or casting we are safe and secure. Are we really?
Recently I have encountered a bug in a production code when dealing with a simple (really simple) usage of a Map. The embarassing part of this issue was that it took lots of effort to debug it and the cause of it was… well… trivial. The code below shows a sketch of how the code looked like before the bug was introduced. In real life the class was a part of a really old and rarely edited legacy code, obviously it was much larger than the one below:

import java.util.HashMap;
import java.util.Map;

public class EmployeeDataLookup {
    // A map storing relation between employee ID and name.
    private Map<Integer, String> employeeIdToName;

    public EmployeeDataLookup() {
        // Create a new EmployeeDataLookup and initialize
        // it with employee names and IDs.
        employeeIdToName = new HashMap<Integer, String>();
        addEmployee(301, "John Doe");
        addEmployee(302, "Mary Poppins");
        addEmployee(303, "Andy Stevens");
    }

    public void addEmployee(int employeeId, String employeeName) {
        employeeIdToName.put(employeeId, employeeName);
    }

    // This class is very complicated and has many other methods...

    // Lookup method for finding employee name for given employee ID.
    public String findEmployeeName(int employeeId) {
        return employeeIdToName.get(employeeId);
    }

    public static void main(String[] args) {
        // Create a EmployeeDataLookup instance
        EmployeeDataLookup employeeLookup = new EmployeeDataLookup();
        // Find the name of an employee with ID = 301
        String employeeName = employeeLookup.findEmployeeName(301);
        System.out.print("Employee 301 : " + employeeName);
    }
}

So what went wrong? Well, at some point the project functionality requirements have changed (surprising, right?) and the key of the map storing data inside of the class had to be changed. In terms of the example above you might say that a company has merged with one of the vendors, so the system storing the employee data had to be made compatible with the ID system of the vendor. Because the vendor company used 13 digit IDs to identify its employees the change to the code in Java terms meant that instead of using Integers we had to change to Longs. Simple right? Its even easier if you use an IDE like Eclipse – just change/refactor the Map key type in line 7 from Integer to Long, let the editor show you all the errors, fix them and that is it! In five minutes all is done:

import java.util.HashMap;
import java.util.Map;

public class EmployeeDataLookup2 {
    // A map storing relation between employee ID and name.
    private Map<Long, String> employeeIdToName;

    public EmployeeDataLookup2() {
        // Create a new EmployeeDataLookup and initialize
        // it with employee names and IDs.
        employeeIdToName = new HashMap<Long, String>();
        addEmployee(301, "John Doe");
        addEmployee(302, "Mary Poppins");
        addEmployee(303, "Andy Stevens");
    }

    public void addEmployee(long employeeId, String employeeName) {
        employeeIdToName.put(employeeId, employeeName);
    }

    // This class is very complicated and has many other methods...

    // Lookup method for finding employee name for given employee ID.
    public String findEmployeeName(int employeeId) {
        return employeeIdToName.get(employeeId);
    }

    public static void main(String[] args) {
        // Create a EmployeeDataLookup instance
        EmployeeDataLookup employeeLookup = new EmployeeDataLookup();
        // Find the name of an employee with ID = 301
        String employeeName = employeeLookup.findEmployeeName(301);
        System.out.print("Employee 301 : " + employeeName);
    }
}

The change above introduced the bug. Can you see it? When you run the main method now you will find out that the name of the employee with ID=301 is ‘null’! Ha!

If you do not see the trouble (or are to lazy to try) I’ll give you a hint: check out the function findEmployeeName . If you have seen it, try to imagine that this class in real life had 1000+ lines of code unrelated to the changed map. Since there are no compile errors it was like looking for a needle in a haystack… so what’s the bug exactly?

The problem is that after introducing generics, probably due to backward compatibility, some of the methods in Collection and Map interface have not been changed and still do not perform type checking. One of them is Map.get(Object) which have caused the bug in the code above. After the ’simple change’ we have still been using Integer keys to access the map that contained Longs, so even though we had a record of employee 301 in our system the get method returned null. And because of the lack of type checking there were no warnings… Busted.

So what’s the lesson from this? Be cautious about type checking even in the most basic situations. Remember that access methods in Sets, Lists and Maps can behave and bite you in the behind. The biggest pain is that the bugs introduced this way are usually hard to spot by a human, so sometimes a dozen of engineers staring at the code can have trouble finding it. There is a way to deal with them though – most of them can be easily found if you are using a static code analysis tool (eg: FindBugs).

Note:
If you are using JDK 6 or higher, its no worries for you. Because in any case you would get the correct result.

Sunday, June 19, 2011

Java Collection Best Practices

1. Decide approximate initial capacity of a collection -  As Collection implementations like ArrayList, HashMap, use Array internally for storing, you can speed up things  by setting initial capacity.

2. Use ArrayLIst, HahMap etc instead of Vector , HashTable to avoid synchronization overhead. Even better use array where ever possible.

3. Program to interface instead of implementation – It gives freedom of switching implementation without touching code.

For Example : Use

List list = new ArrayList();

Avoid :

ArrayList list = new ArrayList();

4. Always return empty collection object instead of null .

For Example : Use

public List getCustomer(){
        //...
        return new ArrayList(0);
}

Avoid :

public List getCustomer(){
        //...
        return null;
    }

5. Generally you use a java.lang.Integer or
a java.lang.String class as the key, which are immutable Java objects.

6. Avoid exposing collection field – Always provide fine grained methods for collection fields instead of directly exposing setter/getter for collection field.

For Example Use :

class  Order
{
    List ArrayLisy itemList;
    //...

    public boolean addItem(Item item){
        //....
    }

    public boolean removeItem(Item item){
        //....
    }
}

Avoid :

class  Order
{
    List ArrayLisy itemList;
    //...

    public void setItems(List items){
        //....
    }

  }

7. Avoid storing unrelated or different types of objects into same collection

For Example Use :

public class  Order
{
    List ArrayLisy itemList;
    //...

    public boolean addItem(Item item){
        //....
    }

    public boolean removeItem(Item item){
        //....
    }

    public static void main(String [] args){
        int id;
        String desc;
        Order order = new Order();
        //...

        Item item = new Item()[
        item.setItem(new Integer(id));
        item.setDesc(dec);
        order.addItem(item);
        //...
    }

}

public class Item
{
    int id;
    String desc;

    public void setId(int id){
        //..
    }

    public int getId(){
        //..
    }

    public void setDesc(){
        //..
    }

    public String getDesc(){
        //..
    }
}

Avoid :

public class  Order
{
    List ArrayLisy itemList;
    //...

    public boolean addItem(Item item){
        //....
    }

    public boolean removeItem(Item item){
        //....
    }

    public static void main(String [] args){
        int id;
        String desc;
        Order order = new Order();
        //...

        List item = new ArrayList()[
        item.add(new Integer(id));
        item.add(dec);
        order.addItem(item);
        //...
    }

   }

8. Use Collection framework features instead of traditional approach.

For Example: Use

//search for duplicate names
for (int i=0;i<nameArray.length ;i++ )
{
    String name = nameArray[i];
    if(nameSet.contains(name)){
        System.out.println("Got Duplicate name = " + name );
    }
}

Avoid:

//search for duplicate names

for (int i=0;i<nameArray.length ;i++ )
{   
    String name = nameArray[i];
    for(int j=0;j<nameArrayLength;j++){
        if(nameArray[j].equals(name)){
            System.out.println("Got Duplicate name = " + name );
        }
    }
}

Sunday, May 29, 2011

Range-view Operation on list

The range-view operation, subList(int fromIndex, int toIndex), returns a List view of the portion of this list whose indices range from fromIndex, inclusive, to toIndex, exclusive. This half-open range mirrors the typical for-loop:

for (int i=fromIndex; i<toIndex; i++) {
...
}


As the term view implies, the returned List is backed by the List on which subList was called, so changes in the former List are reflected in the latter.


This method eliminates the need for explicit range operations (of the sort that commonly exist for arrays). Any operation that expects a List can be used as a range operation by passing a subList view instead of a whole List. For example, the following idiom removes a range of elements from a list:

list.subList(fromIndex, toIndex).clear();



Similar idioms may be constructed to search for an element in a range:


int i = list.subList(fromIndex, toIndex).indexOf(o);
int j = list.subList(fromIndex, toIndex).lastIndexOf(o);


Note that the above idioms return the index of the found element in the subList, not the index in the backing List.

Any polymorphic algorithm that operates on a List (like the replace and shuffle examples, above) works with the List returned by subList.

Here's a polymorphic algorithm whose implementation uses subList to deal a hand from a deck. That is to say, it returns a new List (the "hand") containing the specified number of elements taken from the end of the specified List (the "deck"). The elements returned in the hand are removed from the deck.

public static List dealHand(List deck, int n) {
int deckSize = deck.size();
List handView = deck.subList(deckSize-n, deckSize);
List hand = new ArrayList(handView);
handView.clear();
return hand;
}

 

The literal-minded might say that this program deals from the bottom of the deck, but I prefer to think that the computer is holding the deck upside down. At any rate, for many common List implementations, like ArrayList, the performance of removing elements from the end of the list is substantially better than that of removing elements from the beginning.

Here's a program using the dealHand method in combination with Collections.shuffle to generate hands from a normal 52-card deck. The program takes two command line arguments: the number of hands to deal and the number of cards in each hand.

 

import java.util.*;

class Deal {
public static void main(String args[]) {
int numHands = Integer.parseInt(args[0]);
int cardsPerHand = Integer.parseInt(args[1]);

// Make a normal 52-card deck
String[] suit = new String[] {"spades", "hearts", "diamonds", "clubs"};
String[] rank = new String[]
{"ace","2","3","4","5","6","7","8","9","10","jack","queen","king"};
List deck = new ArrayList();
for (int i=0; i<suit.length; i++)
for (int j=0; j<rank.length; j++)
deck.add(rank[j] + " of " + suit[i]);

Collections.shuffle(deck);

for (int i=0; i<numHands; i++)
System.out.println(dealHand(deck, cardsPerHand));
}
}


Let's run the program:


% java Deal 4 5

[8 of hearts, jack of spades, 3 of spades, 4 of spades, king of diamonds]
[4 of diamonds, ace of clubs, 6 of clubs, jack of hearts, queen of hearts]
[7 of spades, 5 of spades, 2 of diamonds, queen of diamonds, 9 of clubs]
[8 of spades, 6 of diamonds, ace of spades, 3 of hearts, ace of hearts]

While the subList operation is extremely powerful, some care must be exercised when using it. The semantics of the List returned by subList become undefined if elements are added to or removed from the backing List in any way other than via the returned List. Thus, it's highly recommended that you use the List returned by subList only as a transient object, to perform one or a sequence of range operations on the backing List. The longer you use the subList object, the greater the probability that you'll compromise it by modifying the backing List directly (or through another subList object).


 

Positional Access and Search Operations on Lists

The basic positional access operations (get, set, add and remove) behave just like their longer-named counterparts in Vector (elementAt, setElementAt, insertElementAt and removeElementAt) with one noteworthy exception. The set and remove operations return the old value that is being overwritten or removed; the Vector counterparts (setElementAt and removeElementAt) return nothing (void). The search operations indexOf and lastIndexOf behave exactly like the identically named operations in Vector.

The addAll operation inserts all of the elements of the specified Collection starting at the specified position. The elements are inserted in the order they are returned by the specified Collection's iterator. This call is the positional access analogue of Collection's addAll operation.

Here's a little function to swap two indexed values in a List.

private static void swap(List a, int i, int j) {
Object tmp = a.get(i);
a.set(i, a.get(j));
a.set(j, tmp);
}


Of course there's one big difference. This is a polymorphic algorithm: it swaps two elements in any List, regardless of its implementation type. "Big deal," you say, "What's it good for?" Funny you should ask. Take a look at this:


public static void shuffle(List list, Random rnd) {
for (int i=list.size(); i>1; i--)
swap(list, i-1, rnd.nextInt(i));
}


This algorithm (which is included in the JDK's Collections(in the API reference documentation)class) randomly permutes the specified List using the specified source of randomness. It's a bit subtle: It runs up the list from the bottom, repeatedly swapping a randomly selected element into the current position. Unlike most naive attempts at shuffling, it's fair (all permutations occur with equal likelihood, assuming an unbiased source of randomness) and fast (requiring exactly list.size()-1 iterations). The following short program uses this algorithm to print the words in its argument list in random order:


import java.util.*;

public class Shuffle {
public static void main(String args[]) {
List l = new ArrayList();
for (int i=0; i<args.length; i++)
l.add(args[i]);
Collections.shuffle(l, new Random());
System.out.println(l);
}
}


In fact, we can make this program even shorter and faster. The Arrays(in the API reference documentation)class has a static factory method called asList that allows an array to be viewed as a List. This method does not copy the array; changes in the List write through to the array, and vice-versa. The resulting List is not a general-purpose List implementation, in that it doesn't implement the (optional) add and remove operations: arrays are not resizable. Taking advantage of Arrays.asList and calling an alternate form of shuffle that uses a default source of randomness, you get the following tiny program, whose behavior is identical to the previous program:


import java.util.*;

public class Shuffle {
public static void main(String args[]) {
List l = Arrays.asList(args);
Collections.shuffle(l);
System.out.println(l);
}
}

Collection Operations on Lists–Simple and Bulk

Create the lists
List list1 = new ArrayList(); 
List list2 = new ArrayList();


Add the elements


// Add elements to the lists ...
list1.add("Hanuman");

Bulk Add
Copy all the elements from list2 to list1 (list1 += list2). list1 becomes the union of list1 and list2

list1.addAll(list2); 

Bulk Remove
Remove all the elements in list1 from list2 (list1 -= list2). list1 becomes the asymmetric difference of list1 and list2

list1.removeAll(list2); 

Intersection of Lists
Get the intersection of list1 and list2. list1 becomes the intersection of list1 and list2

list1.retainAll(list2); 

Remove all elements from a list

list1.clear(); 


Truncate the list


int newSize = 2;
list1.subList(newSize, list1.size()).clear();

Lists In Java

A List(in the API reference documentation)is an ordered Collection(in the API reference documentation)(sometimes called a sequence). Lists may contain duplicate elements. In addition to the operations inherited from Collection, the List interface includes operations for:

  • Positional Access: manipulate elements based on their numerical position in the list.
  • Search: search for a specified object in the list and return its numerical position.
  • List Iteration: extend Iterator semantics to take advantage of the list's sequential nature.
  • Range-view: perform arbitrary range operations on the list.

List Interface

List Implementations

 

Comparing List to Vector

ListIterator Interface

Operations on Lists

There are various type of operations that can be performed on lists:


Generic Lists in Java
Performance of List implementations in java

Introduction to Sets in java

A Set(in the API reference documentation) is a Collection(in the API reference documentation) that cannot contain duplicate elements. Set models the mathematical set abstraction. The Set interface contains no methods other than those inherited from Collection. It adds the restriction that duplicate elements are prohibited. Set also adds a stronger contract on the behavior of the equals and hashCode operations, allowing Set objects with different implementation types to be compared meaningfully. Two Set objects are equal if they contain the same elements.

The Properties class in java

The Properties class inherits from Hashtable and is part of JDK 1.0. Instances of Properties typically represent persistent values describing something such as system settings. For example, the System.getProperties() method returns a system properties table with various key/value pairs that describe the platform the program is running on.

The Properties class adds additional functionality that can be extremely useful. The Properties class represents a persistent list of properties. What exactly does this mean? The Properties class is designed to provide methods to store and load files containing key-value pairs as Strings. Properties files are simply key-value pairs where the key and value are separated by an "=" (name=Tom) and eack key-value pair is on a separate line. A Windows ini file is an example of a properties file. In many cases, XML files are replacing properties files but the simplicity of a properties file combined with its ease of use makes the Properties class still a very useful class.

Although the Properties file inherits the methods of the Hashtable, it is recommended that the Hashtable put method not be used as this may allow the insertion of non-String objects. Only Strings should be used as either a key or a value in a Properties object. A Properties object with a non-String in it will throw an exception if you attempt to store it to a file. A Properties object can contain another Properties object (specified in the constructor) which is used as the default keys if no matching key is found in the Properties object.

Methods in Property class

The Properties class provides several new methods:

  • Object setProperty(String key, String value) - Invokes the Hashtable put method. Although it returns an Object, the return should always be a String.
  • String getProperty(String key) - Returns the value found for the matching key. Null if no match is found.
  • String getProperty(String key, String defaultValue) - Returns the value found for the matching key.The defaultValue is returned if no match is found.
  • void list(PrintStream output) - Writes the Properties object out to the specified PrintStream.
  • void list(PrintWriter output) - Writes the Properties object out to the specified PrintWriter.
  • void load(InputStream input) - Loads data into the Properties object using the specified InputStream.Key-value pairs are assumed to be on separate lines and each kei is separated from its value by an equals sign ("="). In addition to the equals sign, a colon (":") or the first white space will be used as a separator when reading in a properties file.
  • void store(OutputStream output, String header) - Writes the Properties object out to the specified OutputStream. The header is written as a comment line at the beginning of the file. After the header line, another comment line is written containing the current date and time. A "#" is placed at the beginning of these lines to identify them as comments. The OutputStream will be flushed but will remain open. Any properties in the default Properties object are not written to the output.

Example of Properties class in java

Property class example in java

Here is an example of reading in a properties file, removing the password and printing out the reminder.
import java.util.*;
import java.io.*;

public class PropertyDemo {

public static void main(String[] args) 
                         throws Exception {

BufferedInputStream bStream = new BufferedInputStream
              (new FileInputStream("prefs.ini"));
Properties props = new Properties();
props.load(bStream);
props.remove("password");
props.list(System.out);
bStream.close();
}
} 

LinkedHashMap in java

New to J2SE 1.4, the LinkedHashMap class is used in exactly the same way as the HashMap class. It has no additional methods but it does have one additional constructor that we will discuss in a moment. The basic difference between HashMap and LinkedHashMap is that the LinkedHashMap maintains the order of the items added to the Map. It does this by maintaining a doubly linked list containing the hash and the original order of the items. According to Sun, the LinkedHashMap should run nearly as fast as the HashMap.

The LinkedHashMap has one additional constructor that takes an additional boolean parameter. This allows you to construct a LinkedHashMap that maintains items, not in the order that they are added to the Map but rather in the order in which they are accessed.

Example of LinkedHashMap

LinkedHashMap example in java

This example shows LinkedHashMap in java:

public class JavaLinkedHashMapExample {
public static void main(String[] args) {
//create object of LinkedHashMap
LinkedHashMap lHashMap = new LinkedHashMap();
//put the values
lHashMap.put("One", new Integer(1));
lHashMap.put("Two", new Integer(2));
//get the value
Object obj = lHashMap.get("One");
System.out.println(obj);
//iterate over linked hash map values
Collection c = lHashMap.values();

//obtain an Iterator for Collection
Iterator itr = c.iterator();



//iterate through LinkedHashMap values iterator
while(itr.hasNext())
System.out.println(itr.next());
}
}

Saturday, May 28, 2011

The IdenitityHashMap Class in java

The IdentityHashMap is also like the HashMap with the exception that a key is considered equal to another key only if they are pointing to the exact same object. Other implementations of Map use the equals( ) method to determine if two keys are equal. The IdentityHashMap uses the == comparator. Two keys (a and b) are considered equal if a == b. The IdentityhashMap should only be used in the cases where this functionality is required. It should not be used otherwise.

HashTable in java

Hashtable was part of the original java.util and is a concrete implementation of a Dictionary. However, Java 2 reengineered Hashtable so that it also implements the Map interface. Thus, Hashtable is now integrated into the collections framework. It is similar to HashMap, but is synchronized.

Like HashMap, Hashtable stores key/value pairs in a hash table. When using a Hashtable, you specify an object that is used as a key, and the value that you want linked to that key. The key is then hashed, and the resulting hash code is used as the index at which the value is stored within the table.

A hash table can only store objects that override the hashCode() and equals() methods that are defined by Object. The hashCode() method must compute and return the hash code for the object. Of course, equals() compares two objects. Fortunately, many of Java's built-in classes already implement the hashCode() method. For example, the most common type of Hashtable uses a String object as the key. String implements both hashCode() and equals().

Constructors of HashTable class

Hashtable( )
Hashtable(int size)
Hashtable(int size, float fillRatio)
Hashtable(Map m)

 

The first version is the default constructor. The second version creates a hash table that has an initial size specified by size. The third version creates a hash table that has an initial size specified by size and a fill ratio specified by fillRatio. This ratio must be between 0.0 and 1.0, and it determines how full the hash table can be before it is resized upward. Specifically, when the number of elements is greater than the capacity of the hash table multiplied by its fill ratio, the hash table is expanded. If you do not specify a fill ratio, then 0.75 is used. Finally, the fourth version creates a hash table that is initialized with the elements in m. The capacity of the hash table is set to twice the number of elements in m. The default load factor of 0.75 is used. The fourth constructor was added by Java 2.

 

Examples on HashTable


TreeMap in Java Collections

The TreeMap class guarantees that the keys in the Map will be sorted in ascending order by either the keys natural order or by a Comparator provided to the constructor of the TreeMap. TreeMap implements Map and SortedSet interfaces and extends AbstractMap. TreeMap keeps the balanced binary tree in sorted order by key.

Searching for an item in a TreeMap will be slower than in a HashMap because the hashing algorithm gives better performance than the compareTo() method which is used to locate items in a TreeMap.

 

Creating a TreeMap – Constructors for TreeMap

It has the following constructors. Here comp stands for Comparator, mp stands for Map, smp stands for SortedMap.

Result Constructor Description
tmap = new TreeMap() Creates new TreeMap. Keys sorted by natural order.
tmap = new TreeMap(comp) Creates new TreeMap using Comparator comp to sort keys.
tmap = new TreeMap(mp) Creates new TreeMap from Map mp using natural ordering.
tmap = new TreeMap(smp) Creates new TreeMap from SortedMap smp using key ordering from smp.


 

Methods in TreeMap

TreeMap adds the methods from Map and SortedMap. See the methods of these interfaces – Methods in Map interface, Methods in SortedMap interface.

So other than Map interface methods it has SortedMap interface Methods:

  • Object firstKey() - Gets the first key from the sorted Map.
  • Object lastKey() - Gets the last key from the sorted map.
  • SortedMap headMap(Object toKey) - Returns a view of the portion of this Map whose keys are less than toKey.
  • SortedMap tailMap(Object fromKey) - Returns a view of the portion of this Map whose keys are greater than or equal to fromKey.
  • SortedMap subMap(Object fromKey, Object toKey) - Returns a view of the portion of this Map whose starting key is greater than or equal to fromKey and whose ending key is less than toKey.

 

Example

TreeMap Example in java

TreeMap Example in java

This example covers tree-map example in java:

TreeMap tm = new TreeMap();
// Put elements to the map
tm.put("Kinshuk Chandra", new Double(3434.34));
tm.put("Himanshu Singh", new Double(123.22));
tm.put("Gaurav Mishra", new Double(1378.00));
tm.put("Mohit Mittal", new Double(99.22));
tm.put("Chitranshu Mishra", new Double(-19.08));
// Get a set of the entries
Set set = tm.entrySet();
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println();
// Deposit 1000 into My (Kinshuk Chandra's) account
double balance = ((Double)tm.get("Kinshuk Chandra")).doubleValue();
tm.put("Kinshuk Chandra", new Double(balance + 1000));
System.out.println("Kinshuk Chandra's new balance: " +
tm.get("Kinshuk Chandra"));

 

Output:

Chitranshu Mishra: -19.08
Gaurav Mishra: 1378.0
Himanshu Singh: 123.22
Kinshuk Chandra: 3434.34
Mohit Mittal: 99.22

Kinshuk Chandra's current balance: 4434.34


 

Notice that TreeMap sorts the keys. However, in this case, they are sorted by first name instead of last name. You can alter this behavior by specifying a comparator when the map is created.

Chitika