Solved

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

Posted on 2013-11-20
9
410 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 26

Expert Comment

by:dpearson
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:Tolgar
Comment Utility
@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
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Author Comment

by:Tolgar
Comment Utility
Any ideas?
0
 

Author Comment

by:Tolgar
Comment Utility
Ok. problem solved :)
0
 
LVL 35

Expert Comment

by:mccarl
Comment Utility
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
Comment Utility
Thanks!
0
 
LVL 35

Expert Comment

by:mccarl
Comment Utility
No problem! :)
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
best (free) software to access postgres db (java) 1 17
move one pixel 4 38
Not needed 13 53
maven project error 5 17
This is an explanation of a simple data model to help parse a JSON feed
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…

763 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

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now