Solved

How to keep two values under the same key in a hashmap in JAVA?

Posted on 2013-11-20
9
424 Views
Last Modified: 2013-11-21
Hi,
I have a Java code which I read some data from a database. My code works fine but as of now, I only have one value for each key in the hashmap that I have below.

However, I now need to keep two values that corresponds to the same key in the hashmap.

My current code to read data from the database is like this:

    public List<HashMap<Integer, String>> getFullCheckList() throws ClassNotFoundException, SQLException{
        Class.forName("com.mysql.jdbc.Driver") ;
        Connection conn = DriverManager.getConnection("jdbc:mysql://SOMEDATABASE", "SOMEDATABASENAME", "SOMEPASSWORD") ;
        Statement stmt = conn.createStatement() ;
        String queryMtcheckName = "SELECT `name`, `id` FROM `mtcheck`" ;
        ResultSet rs = stmt.executeQuery(queryMtcheckName) ;
        ArrayList<HashMap<Integer, String>> checkList = new ArrayList<HashMap<Integer, String>>();
        while(rs.next()) {
            //System.out.println("rs: " + rs);
            HashMap<Integer, String> check = new HashMap<Integer, String>();
            Integer anId = rs.getInt("Id");
            String aName = rs.getString("Name");
            //System.out.println("anId : " + anId );
            //System.out.println("aName : " + aName );
            check.put(anId , aName );  //I NEED TO PUT ONE MORE VALUE THAT CORRESPONDS TO THE SAME KEY IN HERE WHICH I WILL GET BY aType = rs.getString("Type")
            //System.out.println("check: " + rs);
            checkList.add(check);
        }
        rs.close();
        stmt.close();
        conn.close();
        //System.out.println("checkList:" + checkList);
        return checkList;
    }

Open in new window


In addition to "Name", I now want to get the "Type" from "rs" as the following and I want to put this other value, which is a "Type", that corresponds to the same key with the "Name" value:

String aType = rs.getString("Type");

Open in new window


Basically, I need to save two values for one key.

And then I pass this "checkList" to another class and I do this operation:

            item_MtStandards = new TreeItem(tree, SWT.NONE);
            item_MtStandards.setText("MtStandards");
            
            Iterator<HashMap<Integer, String>> checkListIter = checkList.iterator();
            while(checkListIter.hasNext()) {
              HashMap<Integer, String> amap =   (HashMap<Integer, String>) checkListIter .next();
              Set<?> keysetString = (Set<?>) amap .keySet();
              Iterator<?> iter = keysetString.iterator();
              while( iter.hasNext() ) {
                Integer keyVal = (Integer) iter.next();
                //System.out.println("keyVal " + keyVal);
                String valFromKey = amap.get(keyVal);
                //System.out.println("valFromKey " + valFromKey);
                TreeItem item_MtSubstandards = new TreeItem(item_MtStandards, SWT.NONE);
                item_MtSubstandards.setText(valFromKey);
              } 
            }

Open in new window


I want to change this code as the following so that I will be able to use the "Type" as the control value and the "Name" as the actual value to be set for the text:

            item_MtCppStandards = new TreeItem(tree, SWT.NONE);
            item_MtCppStandards.setText("CppStandards");

            item_MtJavaStandards = new TreeItem(tree, SWT.NONE);
            item_MtJavaStandards.setText("JavaStandards");

            item_MtOtherStandards = new TreeItem(tree, SWT.NONE);
            item_MtOtherStandards.setText("OtherStandards");
            
            Iterator<HashMap<Integer, String>> checkListIter = checkList.iterator();
            while(checkListIter.hasNext()) {
              HashMap<Integer, String> amap =   (HashMap<Integer, String>) checkListIter .next();
              Set<?> keysetString = (Set<?>) amap .keySet();
              Iterator<?> iter = keysetString.iterator();
              while( iter.hasNext() ) {
                Integer keyVal = (Integer) iter.next();
                //System.out.println("keyVal " + keyVal);
                String val1FromKey = amap.get(keyVal); //THIS IS SUPPOSED TO GIVE ME THE "Type"
                String val2FromKey = amap.get(keyVal); //THIS IS SUPPOSED TO GIVE ME THE "Name"
                //System.out.println("valFromKey " + valFromKey);
                if (val1FromKey.equals("Cpp")){
                TreeItem item_MtCppSubstandards = new TreeItem(item_MtCppStandards, SWT.NONE);
                item_MtCppSubstandards.setText(val2FromKey );
} else if (val1FromKey.equals("Java")){
                TreeItem item_MtJavaSubstandards = new TreeItem(item_MtJavaStandards, SWT.NONE);
                item_MtJavaSubstandards.setText(val2FromKey );
              }else {
                 TreeItem item_MtOtherSubstandards = new TreeItem(item_MtOtherStandards, SWT.NONE);
                item_MtOtherSubstandards.setText(val2FromKey );
              }
              } 
            }

Open in new window



So, my main questions are:
- how to keep two values for one key?
- how to get these two values separately by using the corresponding key?

Thanks,
0
Comment
Question by:Tolgar
9 Comments
 
LVL 27

Expert Comment

by:dpearson
ID: 39665021
I think you want to use a Map of Maps.

Map<Integer, Map<String, String>> multiMap ;

So each row in the database is itself a map:

Map<String, String> rowMap ;
rowMap.put("name", name) ;
rowMap.put("type", type) ;

and then you put that into the main map:
multiMap.put(key, rowMap) ;

So to get back the name from a given key it's
String name = multiMap.get(key).get("name") ;

And similarly for the type:
String type = multiMap.get(key).get("type") ;

Doug
0
 
LVL 11

Expert Comment

by:Manish
ID: 39665038
Put comma separated value.
like
name = firstvalue, secondvalue.
eg.
map.put("name", "firstvalue, secondvalue") ;


Get the "name" value from map and add ,secondValue.
0
 
LVL 35

Accepted Solution

by:
mccarl earned 500 total points
ID: 39665193
Ahh, you shouldn't even be using a Map at all. You only ever have one item in the map, so it is a bit of a waste to have a whole Map. And your code then iterates over the .keySet() of the Map which will only ever be the one key anyway. So, forget about a Map...

What you need to do is to create a small Class to hold one instance of row which contains "id", "name" and "type". Something like this...
public class CheckDetail {
    private Integer id;
    private String name;
    private String type;

    public CheckDetail(Integer id, String name, String type) {
        this.id = id;
        this.name = name;
        this.type = type;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getType() {
        return type;
    }
}

Open in new window

Now your database code looks something like...
    public List<CheckDetail> getFullCheckList() throws ClassNotFoundException, SQLException{
        Class.forName("com.mysql.jdbc.Driver") ;
        Connection conn = DriverManager.getConnection("jdbc:mysql://SOMEDATABASE", "SOMEDATABASENAME", "SOMEPASSWORD") ;
        Statement stmt = conn.createStatement() ;
        String queryMtcheckName = "SELECT `name`, `id`, `type` FROM `mtcheck`" ;
        ResultSet rs = stmt.executeQuery(queryMtcheckName) ;
        List<CheckDetail> checkList = new ArrayList<CheckDetail>();
        while(rs.next()) {
            //System.out.println("rs: " + rs);
            Integer anId = rs.getInt("Id");
            String aName = rs.getString("Name");
            String aType = rs.getString("Type");
            //System.out.println("anId : " + anId );
            //System.out.println("aName : " + aName );
            //System.out.println("aType : " + aType );
            checkList.add(new CheckDetail(anId, aName, aType));
        }
        rs.close();
        stmt.close();
        conn.close();
        //System.out.println("checkList:" + checkList);
        return checkList;
    }

Open in new window

And then the code that uses the returned list is quite a bit simpler, as...
            item_MtCppStandards = new TreeItem(tree, SWT.NONE);
            item_MtCppStandards.setText("CppStandards");

            item_MtJavaStandards = new TreeItem(tree, SWT.NONE);
            item_MtJavaStandards.setText("JavaStandards");

            item_MtOtherStandards = new TreeItem(tree, SWT.NONE);
            item_MtOtherStandards.setText("OtherStandards");
            
            Iterator<CheckDetail> checkListIter = checkList.iterator();
            while(checkListIter.hasNext()) {
              CheckDetail checkDetail = checkListIter.next();

              if (checkDetail.getType().equals("Cpp")){
                TreeItem item_MtCppSubstandards = new TreeItem(item_MtCppStandards, SWT.NONE);
                item_MtCppSubstandards.setText(checkDetail.getName());
              } else if (checkDetail.getType().equals("Java")){
                TreeItem item_MtJavaSubstandards = new TreeItem(item_MtJavaStandards, SWT.NONE);
                item_MtJavaSubstandards.setText(checkDetail.getName());
              } else {
                 TreeItem item_MtOtherSubstandards = new TreeItem(item_MtOtherStandards, SWT.NONE);
                item_MtOtherSubstandards.setText(checkDetail.getName());
              }
            }

Open in new window

0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 

Author Comment

by:Tolgar
ID: 39666156
@mccarl: This is exactly what I want but I forgot to tell you something in my first post.

I am now reading from the "results" table in the database.

This results table has 6 columns and plus one id column. The names of these columns in the results table are:

author_id
cat_id
cls_id
filetype_id
mtcheck_id
tm_id

Open in new window


The first id column has the name "id".

The 6 columns all have some ids that refer to other tables in the database.

These 6 tables only have "id" and "name" columns.

So, the following part of my code should be slightly different:

      String queryMtcheckName = "SELECT `name`, `id`, `type` FROM `mtcheck`" ;
        ResultSet rs = stmt.executeQuery(queryMtcheckName) ;
        List<CheckDetail> checkList = new ArrayList<CheckDetail>();
        while(rs.next()) {
            //System.out.println("rs: " + rs);
            Integer anId = rs.getInt("Id");
            String aName = rs.getString("Name");
            String aType = rs.getString("Type");
            //System.out.println("anId : " + anId );
            //System.out.println("aName : " + aName );
            //System.out.println("aType : " + aType );
            checkList.add(new CheckDetail(anId, aName, aType));
        }

Open in new window


So, I need the actual values that the ids in these 6 columns in the results table refer in other tables.

I think the above code should be something like this but I have some missing parts in the code where I explained in the comments:
String queryResults = "SELECT `mtcheck_id`, `filetype_id` FROM `results`" ;
ResultSet rs = stmt.executeQuery(queryResults ) ;
List<CheckDetail> checkList = new ArrayList<CheckDetail>();
String acheckName;
String afiletypeName;
        while(rs.next()) {
           Integer anId = rs.getInt("id");   //id from the results table

           Integer acheckId = rs.getInt("Id of mtcheck in the results table in here");
           String querymtcheck = "SELECT `name`, WHERE `id == acheckId` FROM `mtcheck`" ;

            ResultSet rs2 = stmt.executeQuery(querymtcheck ) ;

             while(rs2.next()) {    //I may not even need to have while in here because ids are unique and I guess there will be only one result in the resultset
             // This table has only id and name columns
              acheckName = rs2.getString("Name");           
            }

           Integer afileTypeId = rs.getInt("Id of filetype in the results table in here");
           String querymtcheck = "SELECT `name`, WHERE `id == afileTypeId ` FROM `filetype`" ;

          ResultSet rs3 = stmt.executeQuery(querymtcheck ) ;

           while(rs3.next){ //I may not even need to have while in here because ids are unique and I guess there will be only one result in the resultset
              afiletypeName = rs2.getString("Name");
          }  
       checkList.add(new CheckDetail(anId, acheckName, afiletypeName ));
       }

Open in new window


And,

But I am not sure how I should do it? Can you please help me with that code?
0
 

Author Comment

by:Tolgar
ID: 39666710
Any ideas?
0
 

Author Comment

by:Tolgar
ID: 39666894
Ok. problem solved :)
0
 
LVL 35

Expert Comment

by:mccarl
ID: 39667703
I'm glad you solved it ;) but I hope you didn't solve it in code, like you posted above?

To do what you want, you should make the database do all the hard work. So instead of running 1 query to get all the id's and then running 2 queries for each row returned by the first, you can do it all with just 1 query for the whole thing. The query would be something like this (It looks as though you are using mysql which I'm not 100% across, but I'm pretty sure this should be the right syntax, it'll give you the idea anyway)...
SELECT id, m.name AS name, f.name AS type FROM results r, mtcheck m, filetype f WHERE r.mtcheck_id = m.id AND r.filetype_id = f.id

Open in new window

And then you should be able to use the code that I posted before to collect the data from the rows from this query and build the List<CheckDetail>
0
 

Author Comment

by:Tolgar
ID: 39668030
Thanks!
0
 
LVL 35

Expert Comment

by:mccarl
ID: 39668072
No problem! :)
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
Today, the web development industry is booming, and many people consider it to be their vocation. The question you may be asking yourself is – how do I become a web developer?
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question