• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Paul Clapham
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Roland Mueller
  • Piet Souris
Bartenders:

How to refresh a StringBuffer object for creating a HashMap object

 
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I am trying to create a method - 'ReadFile' that would return HashMap object. This object is created by reading an input file and each line of the file is parsed to get the key and value which will be used to create this HashMap object. The problem is when I try to refresh the StringBuffer object - 'value' in the code below. It looks like it wipes out the 'value' values in the HashMap - 'hm'.
Any idea how I could effectively refresh - 'value' in the 'for' loop below? Also, I need to read 2 separate input files where the key values of each of these files will be exactly the same. Then I need to compare these to files based on the key and append the values from each to a third file or in an arraylist/vector (or the into hash?). Later I would be using certain field value to do some mathematical calculation and dump the outputs into a separate file. How would I be able to achieve this in the best possible way? The expected output file/array/vector along with the input files are given below.
Any help would be much appreciated.

Thanks.

code:
public static HashMap readFile(String file_name) {

HashMap hm = new HashMap();
try {
BufferedReader reader = new BufferedReader(new FileReader(file_name));

List list = new ArrayList();
String line = reader.readLine();
while(line != null){
list.add(line);
line = reader.readLine();
}

reader.close();

Pattern p = Pattern.compile(",");
StringBuffer value = new StringBuffer();

Iterator iterator = list.iterator();
while(iterator.hasNext()){

String str = (String) iterator.next();
String[] result = p.split(str);
String key = result[0];
for (int i=1; i<result.length; i++)
{
value.append(result[i] + ',');
}
hm.put(key, value);
value.setLength(0);
}
System.out.println(hm);

} catch(Exception ex){
System.out.println(ex);
}
return hm;
}

input file 1:

1, abc, cde, efg
2, xyz, 000, 111
3, 123, abd, klm

Parsing the above file to have
key : 1, value : abc, cde, efg
key : 2, value : xyz, 000, 111
key : 3, value : 123, abd, klm

input file 2:

1, bcd, xyz, 001
2, jyz, 001, 112
3, 723, abx, olm

Parsed in the same way file 1 is done.

Output file/ArrayList/Vector/Hash would look like -

1, abc, cde, efg, bcd, xyz, 001
2, xyz, 000, 111, jyz, 001, 112
3, 123, abd, klm, 723, abx, olm
 
author
Posts: 4356
45
jQuery Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Depending on the format of your data you could use the Properties.load() method to automatically convert an InputStream (file) into a Properties object (similar to a HashMap in many ways).

The method takes multiple formats for keys/values, so take a look at the API for Properties and see if this would work for you.
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Your problem is that StringBuffers are mutable - you are always putting the same object into the map, so all the values will be the same.

If you replace

hm.put(key, value);

by

hm.put(key, value.toString());

you will put the current value of the StringBuffer into the map in the form of a new, immutable String object, which won't be changed later on.

Does that sound reasonable?
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Ilja for your reply. Well, changing to hm(key, value.toString()) unfortunately did not solve my problem. The values from other keys are getting appended. e.g.

I am getting -

3, abc, cde, efg, bcd, xyz, 001, xyz, 000, 111, jyz, 001, 112, 123, abd, klm, 723, abx, olm

But I guess I need to have the following instead in the 'hm' -

3, 123, abd, klm, 723, abx, olm
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am sorry Ilja I was totally wrong. It worked! I also commented out the value.setLength(0) while making the change to hm.put(key, value.toString()). Putting back value.setLength(0) and the change you suggested did the job.
Any idea how I can get the about the other part of my question (comparing two hashes to create the third array/vector/hash) done?
 
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Stepping back a little, having a map value which *looks* like a list or a set but is represented by a String or a StringBuffer doesn't sound object-oriented to me. Why not use a Set, a List or a user-defined class to hold your Map value?
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am not much familiar with Set or List. So what Jeff is suggesting is I could compare two Set's by the some sort of key from each of these and do the same what I want as I mentioned in my posting?
If possible could you please show me a small code snippet how I can use Set or List for this matter?

Thanks for all the help.
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's hard to overestimate the importance of Java's Collection Framework: http://java.sun.com/docs/books/tutorial/collections/index.html

Here is an example of taking two Maps with the Set values and the same key set, and doing a key-wise union of their values.
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sweet! Works like a charm.
Thanks Jeff!!!
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One last question. It looks like for every key the values from the other key's are getting appended. Do I need to refresh the Set object for value in some way?

What I mean is I am getting like for key 3 values 123, abd, klm,xyz, 000, 111,abc, cde, efg
But expecting only 123, abd, klm

Thanks
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One other thing forgot to mention the order of values of a key is very important for me. e.g. if the input file line has 1, abc, cde, efg the hash should have the 1 (key) and exactly abc, cde, efg (value).
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Tariq Ahsan:
One other thing forgot to mention the order of values [of a key] is very important for me. e.g. if the input file line has 1, abc, cde, efg the hash should have the 1 (key) and exactly abc, cde, efg (value).



Do the values constitute a Set or a List? Lists objects maintain their order. On the other hand, there is a specialized Set, java.util.LinkedHashSet that maintains its insertion order. Check out the API:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/List.html
http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html
http://java.sun.com/j2se/1.5.0/docs/api/java/util/LinkedHashSet.html
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Tariq Ahsan:
One last question. It looks like for every key the values from the other key's are getting appended. Do I need to refresh the Set object for value in some way?

What I mean is I am getting like for key 3 values 123, abd, klm,xyz, 000, 111,abc, cde, efg
But expecting only 123, abd, klm


Post some code. I think you are not creating separate Set objects for each entry -- that was an error you had in your original code.
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's the code what I have now. I'll try out the LinkedHashSet as you suggested for retaining the order of the Set.

import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.lang.String;


public class CompareFiles {

public static void main(String[] argv){

try {
String basefile = argv[0];
String inputfile = argv[1];

HashMap base_hash = readFile(basefile);
HashMap input_hash = readFile(inputfile);
Set entries = base_hash.entrySet();
for (Iterator it = entries.iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
Set val = (Set) entry.getValue();

// loop through info to check for desired value
val.containsAll((Set) input_hash.get(entry.getKey()));
}
System.out.println("Bash Hash : " + base_hash);


} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("\n" + "You must specify the base file and a file name as argument" + "\n");
System.out.println("USAGE: java CompareFiles <BaseFileName> <InputFileName>" + "\n");

}

}


public static HashMap readFile(String file_name) {

HashMap hm = new HashMap();
try {

// Reading file
BufferedReader reader = new BufferedReader(new FileReader(file_name));

List list = new ArrayList();
String line = reader.readLine();
while(line != null){
list.add(line);
line = reader.readLine();
}

reader.close();

// Setting delimiter
Pattern p = Pattern.compile(",");
//StringBuffer val = new StringBuffer();
Set value = new HashSet();

// records are in the array one line per element
// also, each was printed to stout as it was read
Iterator iterator = list.iterator();
while(iterator.hasNext()){

String str = (String) iterator.next();
// Parsing each line by delimiter
String[] result = p.split(str);
// Storing the first value from the String array as the key
String key = result[0];
// Rest of the String array will be the value
for (int i=1; i<result.length; i++)
{
//val.append(result[i] + ',');
value.add(result[i]);
}

System.out.println("Key is " + key + " Value is " + value);
hm.put(key, value);
}

System.out.println("ReadFile " + hm);

} catch(Exception ex){
System.out.println(ex);
}
return hm;
}
}


Here's the 2 input files -

input1 :

1,abc,cde,efg
2,ghi,jkl, lmn
3,nop,pqr,stw

input2 :

1,111,cde,efg
2,222,jkl, lmn
3,333,stv,lmn

Expected output:


1,abc,cde,efg,111,cde,efg
2,ghi,jkl, lmn,222,jkl, lmn
3,nop,pqr,stw,333,stv,lmn

Here's the output I am getting -

%java CompareFiles input1 input2

Key is 1 Value is [cde, abc, efg]
Key is 2 Value is [ghi, lmn, cde, abc, jkl, efg]
Key is 3 Value is [ghi, stw, nop, pqr, lmn, cde, abc, jkl, efg]
ReadFile {3=[ghi, stw, nop, pqr, lmn, cde, abc, jkl, efg], 2=[ghi, stw, nop, pqr, lmn, cde, abc, jkl, efg], 1=[ghi, stw, nop, pqr, lmn, cde, abc, jkl, efg]}
Key is 1 Value is [cde, 111, efg]
Key is 2 Value is [222, lmn, cde, 111, jkl, efg]
Key is 3 Value is [lmn, 222, 333, lmn, cde, stv, 111, jkl, efg]
ReadFile {3=[lmn, 222, 333, lmn, cde, stv, 111, jkl, efg], 2=[lmn, 222, 333, lmn, cde, stv, 111, jkl, efg], 1=[lmn, 222, 333, lmn, cde, stv, 111, jkl, efg]}
Bash Hash : {3=[ghi, stw, nop, pqr, lmn, cde, abc, jkl, efg], 2=[ghi, stw, nop, pqr, lmn, cde, abc, jkl, efg], 1=[ghi, stw, nop, pqr, lmn, cde, abc, jkl, efg]}

Thanks for all your help!
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Looks like using LinkedHashSet instead of just the HashSet is working for me to maintain the order of the value text. Now I am left with finding the way to preventing values from other key's to get appended to a key value.

Thanks!
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I got most of the code working. Except for using 'addAll' for the Set object only picks up the values that are not duplicate. Is there a way to ignore duplication and add the second set to the first one?

Here's the code and output :

import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.lang.String;


public class CompareFiles {

public static void main(String[] argv){

try {
String basefile = argv[0];
String inputfile = argv[1];

HashMap base_hash = readFile(basefile);
HashMap input_hash = readFile(inputfile);
System.out.println("Base Hash: " + base_hash);
System.out.println("Input Hash: " + input_hash);
Set entries = base_hash.entrySet();
for (Iterator it = entries.iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
Set val = (Set) entry.getValue();

// loop through info to check for desired value
val.addAll((Set) input_hash.get(entry.getKey()));
}
System.out.println("Base Hash : " + base_hash);

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("\n" + "You must specify the base file and a file name as argument" + "\n");
System.out.println("USAGE: java CompareFiles <BaseFileName> <InputFileName>" + "\n");

}

}


public static HashMap readFile(String file_name) {

HashMap hm = new HashMap();
try {

// Reading file
BufferedReader reader = new BufferedReader(new FileReader(file_name));

List list = new ArrayList();
String line = reader.readLine();
while(line != null){
list.add(line);
line = reader.readLine();
}

reader.close();

// Setting delimiter
Pattern p = Pattern.compile(",");

// records are in the array one line per element
// also, each was printed to stout as it was read
Iterator iterator = list.iterator();
while(iterator.hasNext()){

String str = (String) iterator.next();
// Parsing each line by delimiter
String[] result = p.split(str);
// Storing the first value from the String array as the key
String key = result[0];
Set value = new LinkedHashSet();
// Rest of the String array will be the value
for (int i=1; i<result.length; i++)
{
value.add(result[i]);
}

System.out.println("Key is " + key + " Value is " + value);
hm.put(key, value);
}

System.out.println("ReadFile " + hm);

} catch(Exception ex){
System.out.println(ex);
}
return hm;
}
}


output:

%java CompareFiles input1 input2

Key is 1 Value is [abc, cde, efg]
Key is 2 Value is [ghi, jkl, lmn]
Key is 3 Value is [nop, pqr, stw]
ReadFile {3=[nop, pqr, stw], 2=[ghi, jkl, lmn], 1=[abc, cde, efg]}
Key is 1 Value is [111, cde, efg]
Key is 2 Value is [222, jkl, lmn]
Key is 3 Value is [333, stv, lmn]
ReadFile {3=[333, stv, lmn], 2=[222, jkl, lmn], 1=[111, cde, efg]}
Base Hash: {3=[nop, pqr, stw], 2=[ghi, jkl, lmn], 1=[abc, cde, efg]}
Input Hash: {3=[333, stv, lmn], 2=[222, jkl, lmn], 1=[111, cde, efg]}
Base Hash : {3=[nop, pqr, stw, 333, stv, lmn], 2=[ghi, jkl, lmn, 222], 1=[abc, cde, efg, 111]}
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I got most of the code working. Except for using 'addAll' for the Set object only picks up the values that are not duplicate. Is there a way to ignore duplication and add the second set to the first one?

Here's the code and output :

import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.lang.String;


public class CompareFiles {

public static void main(String[] argv){

try {
String basefile = argv[0];
String inputfile = argv[1];

HashMap base_hash = readFile(basefile);
HashMap input_hash = readFile(inputfile);
System.out.println("Base Hash: " + base_hash);
System.out.println("Input Hash: " + input_hash);
Set entries = base_hash.entrySet();
for (Iterator it = entries.iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
Set val = (Set) entry.getValue();

// loop through info to check for desired value
val.addAll((Set) input_hash.get(entry.getKey()));
}
System.out.println("Base Hash : " + base_hash);

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("\n" + "You must specify the base file and a file name as argument" + "\n");
System.out.println("USAGE: java CompareFiles <BaseFileName> <InputFileName>" + "\n");

}

}


public static HashMap readFile(String file_name) {

HashMap hm = new HashMap();
try {

// Reading file
BufferedReader reader = new BufferedReader(new FileReader(file_name));

List list = new ArrayList();
String line = reader.readLine();
while(line != null){
list.add(line);
line = reader.readLine();
}

reader.close();

// Setting delimiter
Pattern p = Pattern.compile(",");

// records are in the array one line per element
// also, each was printed to stout as it was read
Iterator iterator = list.iterator();
while(iterator.hasNext()){

String str = (String) iterator.next();
// Parsing each line by delimiter
String[] result = p.split(str);
// Storing the first value from the String array as the key
String key = result[0];
Set value = new LinkedHashSet();
// Rest of the String array will be the value
for (int i=1; i<result.length; i++)
{
value.add(result[i]);
}

System.out.println("Key is " + key + " Value is " + value);
hm.put(key, value);
}

System.out.println("ReadFile " + hm);

} catch(Exception ex){
System.out.println(ex);
}
return hm;
}
}


output:

%java CompareFiles input1 input2

Key is 1 Value is [abc, cde, efg]
Key is 2 Value is [ghi, jkl, lmn]
Key is 3 Value is [nop, pqr, stw]
ReadFile {3=[nop, pqr, stw], 2=[ghi, jkl, lmn], 1=[abc, cde, efg]}
Key is 1 Value is [111, cde, efg]
Key is 2 Value is [222, jkl, lmn]
Key is 3 Value is [333, stv, lmn]
ReadFile {3=[333, stv, lmn], 2=[222, jkl, lmn], 1=[111, cde, efg]}
Base Hash: {3=[nop, pqr, stw], 2=[ghi, jkl, lmn], 1=[abc, cde, efg]}
Input Hash: {3=[333, stv, lmn], 2=[222, jkl, lmn], 1=[111, cde, efg]}
Base Hash : {3=[nop, pqr, stw, 333, stv, lmn], 2=[ghi, jkl, lmn, 222], 1=[abc, cde, efg, 111]}
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What do you mean by "Is there a way to ignore duplication and add the second set to the first one" Doesn't the semantics of Set mean that duplicates are ignored?
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
My mistake. I meant to say is there a way to retain duplication while adding one set to another?
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Back in my post of December 20, 2005 06:40 PM, I asked if your values constituted a Set or a List, and I don't know if you pondered that further, but now it sounds like you need a list. So, change Set to List and change LinkedHashSet to ArrayList.
[ December 21, 2005: Message edited by: Jeff Albrechtsen ]
 
Tariq Ahsan
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's the modified code:

import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.lang.String;


public class CompareFiles {

public static void main(String[] argv){

try {
String basefile = argv[0];
String inputfile = argv[1];
List val = new ArrayList();

HashMap base_hash = readFile(basefile);
HashMap input_hash = readFile(inputfile);
System.out.println("Base Hash: " + base_hash);
System.out.println("Input Hash: " + input_hash);
Set entries = base_hash.entrySet();
for (Iterator it = entries.iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
val = (List) entry.getValue();

// loop through info to check for desired value
val.add((List) input_hash.get(entry.getKey()));
System.out.println("Val : " + val);

}

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("\n" + "You must specify the base file and a file name as argument" + "\n");
System.out.println("USAGE: java CompareFiles <BaseFileName> <InputFileName>" + "\n");

}

}


public static HashMap readFile(String file_name) {

HashMap hm = new HashMap();
try {

// Reading file
BufferedReader reader = new BufferedReader(new FileReader(file_name));

List list = new ArrayList();
String line = reader.readLine();
while(line != null){
list.add(line);
line = reader.readLine();
}

reader.close();

// Setting delimiter
Pattern p = Pattern.compile(",");

// records are in the array one line per element
// also, each was printed to stout as it was read
Iterator iterator = list.iterator();
while(iterator.hasNext()){

String str = (String) iterator.next();
// Parsing each line by delimiter
String[] result = p.split(str);
// Storing the first value from the String array as the key
String key = result[0];
//Set value = new LinkedHashSet();
List value = new ArrayList();
// Rest of the String array will be the value
for (int i=1; i<result.length; i++)
{
value.add(result[i]);
}

hm.put(key, value);
}

} catch(Exception ex){
System.out.println(ex);
}
return hm;
}
}


Input files :

input1 :

1,abc,cde,efg
2,ghi,jkl, lmn
3,nop,pqr,stw


input2 :

1,111,cde,efg
2,222,jkl, lmn
3,333,stv,lmn


% java CompareFiles input1 input2

Base Hash: {3=[nop, pqr, stw], 2=[ghi, jkl, lmn], 1=[abc, cde, efg]}
Input Hash: {3=[333, stv, lmn], 2=[222, jkl, lmn], 1=[111, cde, efg]}
Val : [nop, pqr, stw, [333, stv, lmn]]
Val : [ghi, jkl, lmn, [222, jkl, lmn]]
Val : [abc, cde, efg, [111, cde, efg]]


How can I get the above output of 'Val' as -


Val : [1, nop, pqr, stw, 333, stv, lmn]
Val : [2, ghi, jkl, lmn, 222, jkl, lmn]
Val : [3, abc, cde, efg, 111, cde, efg]

The appended list from the second input file (input2) to the first file (input1) matched by key gets stored as a separate array list. Also like to have the 'key' in this list.

Please help!

Thanks
reply
    Bookmark Topic Watch Topic
  • New Topic