Saturday, 12 July 2014

How to sort a Map on the values in Java?

Goal

In this post we will see how can we sort a Map based on its values. We will use Comparators.

Map overview in Java - 


Code :

 /*
 * author : athakur
 */

public class HelloWorld {


    public static void main(String args[]) {
       
        Map<String,Integer> nameAgeMap = new HashMap<String,Integer>();
        AgeComparator ageComparator =  new AgeComparator(nameAgeMap);
        Map<String,Integer> sortedNameAgeMap = new TreeMap<String,Integer>(ageComparator);

        nameAgeMap.put("Name1",21);
        nameAgeMap.put("Name2",16);
        nameAgeMap.put("Name3",10);
        nameAgeMap.put("Name4",23);

        System.out.println("Original Map : "+ nameAgeMap);
       
        sortedNameAgeMap.putAll(nameAgeMap);

        System.out.println("Sorted Name Age Map : "+ sortedNameAgeMap);
       
    }

}

class AgeComparator implements Comparator<String> {
   
    Map<String,Integer> mapToBeCompared;
   
    public AgeComparator(Map<String,Integer> mapToBeCompared){
        this.mapToBeCompared = mapToBeCompared;
    }

    @Override
    public int compare(String o1, String o2) {
        Integer x = mapToBeCompared.get(o1);
        Integer y = mapToBeCompared.get(o2);
        if(x >= y) {
            return 1;
        }
        else {
            return -1;
        }
    }
   
}


Output :


The output is as expected

Original Map : {Name4=23, Name3=10, Name2=16, Name1=21}
Sorted Name Age Map : {Name3=10, Name2=16, Name1=21, Name4=23}

 Note

  1. Above comparator imposes orderings that are inconsistent with equals. 
  2. Do not return 0 from the comparator as it will merge the keys. Given that all keys in a Map are unique. Duplicate key entry over writes the old entry.
  3. If you have your own class instead of Integer in the map then it makes sense for your class to implement comparable interface and use compareTo() directly in compare() method. 
  4. Collection APIs provide sort method that takes comparator as an argument. You can use that for the sorting criteria that suits your requirement. 
To summarize if you want to sort objects based on natural order then use Comparable in Java and if you want to sort on some other attribute of object then use Comparator in Java.

Using Comparator on Entry 

You can create a comparator on Entry which is datastructure that HashMap internally uses - 

public class SortMapByValue
{
    public static boolean ASC = true;
    public static boolean DESC = false;

    public static void main(String[] args)
    {

        // Creating dummy unsorted map
        Map<String, Integer> unsortMap = new HashMap<String, Integer>();
        unsortMap.put("B", 55);
        unsortMap.put("A", 80);
        unsortMap.put("D", 20);
        unsortMap.put("C", 70);

        System.out.println("Before sorting......");
        printMap(unsortMap);

        System.out.println("After sorting ascending order......");
        Map<String, Integer> sortedMapAsc = sortByComparator(unsortMap, ASC);
        printMap(sortedMapAsc);


        System.out.println("After sorting descindeng order......");
        Map<String, Integer> sortedMapDesc = sortByComparator(unsortMap, DESC);
        printMap(sortedMapDesc);

    }

    private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap, final boolean order)
    {

        List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());

        // Sorting the list based on values
        Collections.sort(list, new Comparator<Entry<String, Integer>>()
        {
            public int compare(Entry<String, Integer> o1,
                    Entry<String, Integer> o2)
            {
                if (order)
                {
                    return o1.getValue().compareTo(o2.getValue());
                }
                else
                {
                    return o2.getValue().compareTo(o1.getValue());

                }
            }
        });

        // Maintaining insertion order with the help of LinkedList
        Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
        for (Entry<String, Integer> entry : list)
        {
            sortedMap.put(entry.getKey(), entry.getValue());
        }

        return sortedMap;
    }

    public static void printMap(Map<String, Integer> map)
    {
        for (Entry<String, Integer> entry : map.entrySet())
        {
            System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue());
        }
    }
}

This will sort your HashMap.

Important Links

Sunday, 6 July 2014

Installing Mercurial on Linux

Background

There are many source code versioning tools. Some of them which I have previously used are perforce(p4), git, svn. There are more like cvs, mercurial and the list goes on.... In this post we will see how to install and configure mercurial.

Mercurial is a free, distributed source control management tool. It efficiently handles projects of any size and offers an easy and intuitive interface. (official site)

Mercurial is a cross-platform, distributed revision control tool for software developers. It is mainly implemented using the Python programming language, but includes a binary diff implementation written in C. It is supported on MS Windows and Unix-like systems, such as FreeBSD, Mac OS X and Linux. Mercurial is primarily a command line program but graphical user interface extensions are available. All of Mercurial's operations are invoked as arguments to its driver program hg, a reference to the chemical symbol of the element mercury. (More on Wiki)

Installation

You can easily to the installation using a package manager

sudo apt-get install mercurial

But for me it installed a very old version (2.0.2) which is clearly not the way to go. So you can install the latest version as follows - 


sudo apt-get install python-setuptools python-dev build-essential
sudo easy_install -U mercurial

This installed the latest version for me (3.0.1). You can view the version installed by

hg version


Configuration file for the same can be found in  /etc/mercurial/hgrc. You can edit it to suit your requirements.

I have added external diff program called kdiff3 ( How to Install Kdiff3 on Ubuntu  ). So my hgrc file contents are as follows

# system-wide mercurial configuration file
# See hgrc(5) for more information

[merge-tools]
kdiff3.args=--auto -L1 base --L2 local --L3 other $base $local $other -o $output
kdiff3.regkey=Software\KDiff3
kdiff3.regappend=\kdiff3.exe
kdiff3.fixeol=True
kdiff3.gui=True 

Important Links

How to Install Kdiff3 on Ubuntu

Background

Subversion, Git, Mercurial and others support three-way merges (combining mine, theirs, and the "base" revision) and support graphical tools to resolve conflicts.

Which tool do we use ?  In this post I will show how can we install KDiff3.
 It is an open source cross platform tool.


 

Installation

  1. Download the Kdiff3 tar file from the sourceforge repos, then extract the tar file. The sourceforge link for the Kdiff3 project.
  2. Extract the tar.gz file using tar command

    tar -xzf kdiff3-0.9.98.tar.gz
  3. Make sure you have QT4 installed . If not installed you can install it with following command -

    sudo apt-get install libqt4-dev
  4. After extracting go into the “src-QT4″ directory and compile

    cd kdiff3-0.9.98/src-QT4
    qmake kdiff3.pro
    make
    sudo make install
  5. Now you should be able to launch the program by typing kdiff3 in the console.




Important Links

Saturday, 5 July 2014

Resolving issue with Ubuntu installation getting stuck at VMware tools installation.

Background of the problem

I was installing Ubuntu 12.04 LTS on VMware.
I used the "Easy Mode" option while installation.
When I finish the installation, the VMware automatically tried to install VMware Tools and it was stuck. No graphical interface could be loaded. Restarting the VM and rebooting Ubuntu did not help.

You will get something like following


******************************************************************
******************************************************************
Vmware Easy Install

PLEASE WAIT! VMware Tools is currently being 
installed on your system. Depending on the 
version of Ubuntu you are installing, you may 
log in below and use the system during 
intallation. Otherwise, please wait for the 
graphical environment to launch. Thank you.

******************************************************************
******************************************************************
ubuntu login:_


Some random Screenshot I picked up from the net as I already resolved my issue :) . It looked same as below -



Solution


Follow 3 steps mentioned below

  1. Restore the /etc/issue file:

    Use the command : sudo mv /etc/issue.backup /etc/issue
  2. Restore the /etc/rc.local file:

    Use the command :  sudo mv /etc/rc.local.backup /etc/rc.local
  3. Restore the /etc/init/lightdm.conf file:

    Use the command : sudo mv /opt/vmware-tools-installer/lightdm.conf /etc/init

And then simply reboot your machine. You should see graphical interface coming up now.

But this also leds to another problem. This does not install your vmware tools. On trying you would get the following error.






To fix this delete and re add drives


    1. Power off the virtual machine.
    2. Go to VM > Settings
    3. Select CD/DVD.
    4. Make a note of the current settings for this device, then click Remove.
    5. Click Add.
    6. Select CD/DVD, and click Next.
    7. Select the settings you noted previously (or you can set them later), and click Next > Finish.
    8. Select Floppy.
    9. Make a note of the current settings for this device, then click Remove.
    10. Click Add.
    11. Select Floppy, and click Next.
    12. Select the settings you noted previously (or you can set them later), and click Next > Finish.
    13.Power on the virtual machine and install VMware Tools.

This should install vmware tools.

Note : To install the vmware tools if you get popup saying CD is read only don't worry. Copy the tar.gz file to your home folder. Extract folder contents using tar -xvf filename  and then install it. There is a python script in the extracted folder (ends with extension .py). Simply run it sudo ./filename.py and your vmware tools should get installed.

Friday, 4 July 2014

How to permanently set $PATH on Linux?

Goal

Very basic information that every Linux user needs to know - How to export $PATH . This variable contains all the paths which may have executables that will be recognized throughout the System. For example lets say you installed java. You want to compile a program and so you do javac TestClass.java and you get javac is not a recognized command. One way to resolve this is to do pathtojdk/bin/javac TestClass.java but this is not the best way. You can add path pathtojdk/bin to that $PATH environment variable and then you can access all commands in bin folder from anywhere in your System. So lets see how can we achieve this...

Getting Started...

So lets say I want to add following 3 paths to $PATH env variable
  1. $HOME/mozilla/adt-bundle-linux/sdk/tools
  2. $HOME/mozilla/adt-bundle-linux/sdk/build-tools
  3. $HOME/mozilla/adt-bundle-linux/sdk/platform-tools
You can view your existing $PATH variable by just typing echo $PATH . To add it you can do the following. Execute the following on command line

export PATH=$PATH:$HOME/mozilla/adt-bundle-linux/sdk/tools:$HOME/mozilla/adt-bundle-linux/sdk/build-tools:$HOME/mozilla/adt-bundle-linux/sdk/platform-tools

then again you can check the $PATH variable using echo.



But wait a second. Restart the console and if you notice the exported PATH is gone. Yes it is lasts only for that console session. So lets see how can we export this $PATH permanently.


  1. Edit your ~/.bashrc file and add the export line there.
  2. Save the file.
  3. Lastly execute source ~/.bashrc
Note : source command is basically to make your console aware of the changes that you have made in the file.


and thats it. Those PATHS should be in your $PATH environment variable permanently from there on.

Caution

  • It's often considered a security hole to leave a trailing colon at the end of your bash PATH because it makes it so that bash looks in the current directory if it can't find the executable it's looking for.  
  • Consider the scenario when you unpack a tarball, then cd to the directory you unpacked it in, then run ls---and then realize that the tarball had a malicious program called ls in it.
  • There can be other, more nasty versions. For instance, creating a malicious script called sl and waiting for someone to mistype ls.   

Related Links

t> UA-39527780-1 back to top