File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes How to refresh a StringBuffer object for creating a HashMap object Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "How to refresh a StringBuffer object for creating a HashMap object" Watch "How to refresh a StringBuffer object for creating a HashMap object" New topic
Author

How to refresh a StringBuffer object for creating a HashMap object

Tariq Ahsan
Ranch Hand

Joined: Nov 03, 2003
Posts: 116
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
Scott Selikoff
Saloon Keeper

Joined: Oct 23, 2005
Posts: 3697
    
    5

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.


My Blog: Down Home Country Coding with Scott Selikoff
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
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?


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Tariq Ahsan
Ranch Hand

Joined: Nov 03, 2003
Posts: 116
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

Joined: Nov 03, 2003
Posts: 116
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?
Jeff Albertson
Ranch Hand

Joined: Sep 16, 2005
Posts: 1780
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?


There is no emoticon for what I am feeling!
Tariq Ahsan
Ranch Hand

Joined: Nov 03, 2003
Posts: 116
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

Joined: Sep 16, 2005
Posts: 1780
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

Joined: Nov 03, 2003
Posts: 116
Sweet! Works like a charm.
Thanks Jeff!!!
Tariq Ahsan
Ranch Hand

Joined: Nov 03, 2003
Posts: 116
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

Joined: Nov 03, 2003
Posts: 116
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

Joined: Sep 16, 2005
Posts: 1780
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

Joined: Sep 16, 2005
Posts: 1780
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

Joined: Nov 03, 2003
Posts: 116
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

Joined: Nov 03, 2003
Posts: 116
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

Joined: Nov 03, 2003
Posts: 116
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

Joined: Nov 03, 2003
Posts: 116
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

Joined: Sep 16, 2005
Posts: 1780
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

Joined: Nov 03, 2003
Posts: 116
My mistake. I meant to say is there a way to retain duplication while adding one set to another?
Jeff Albertson
Ranch Hand

Joined: Sep 16, 2005
Posts: 1780
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

Joined: Nov 03, 2003
Posts: 116
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
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: How to refresh a StringBuffer object for creating a HashMap object
 
Similar Threads
Reading a stream from a socket
Using HashMap on a text string
comparing and appending two vectors
comparing two comma delimited files
reading from a properties file