问题
Say I have a hashmap with String
type as key and ArrayList
type as value, example {"value1"=["one","three","five"], "value2"=["two","four","six"]}
where "value1" and "value2" are keys. I want to write the above hashmap data in following format. (so that I can read the csv file in excel)
value1,value2
one,two
three,four
five,six
My idea was to write the first key and its values as follows
value1
one
three
five
Then I was thinking of using the seek method in RandomAccessFile
class to back to line 1 and again write the second key and its values. However I am not able to accomplish this task since seek function takes in the length of strings in the entire file and writes the new string after it. While I wanted the pointer to jump to the first line and append the string. Is there a better way to do this?. A quick example would be much appreciated.
Thanks
回答1:
Why can't you just use 4 Strings, one for each row? Something like this:
StringBuilder keyRow = new StringBuilder();
StringBuilder value1 = new StringBuilder();
StringBuilder value2 = new StringBuilder();
StringBuilder value3 = new StringBuilder();
Iterator keys = hashmap.keySet().iterator();
boolean notFirst = true;
while(keys.hasNext()) {
String key = (String)keys.next();
ArrayList list = (ArrayList)hashmap.get(key);
if(!notFirst) {
keyRow.append(",");
value1.append(",");
value2.append(",");
value3.append(",");
}
keyRow.append(key);
value1.append((String)list.get(0));
value2.append((String)list.get(1));
value3.append((String)list.get(2));
notFirst = false;
}
Then at the end, just take the 4 Strings
String csv = keyRow.toString()+"\n"+value1.toString()+"\n"+value2.toString()+"\n"+value3.toString();
Note that this example isn't really proper CSV. Strings with commas aren't wrapped in quotes.
Or you iterate through the HashMap a thousand times if you have thousands of these rows. To save a bit of time from looking up a key, you can put them all in an ArrayList
:
StringBuilder csv = new StringBuilder();
int row = 0;
ArrayList<ArrayList> list = new ArrayList<ArrayList>();
// Write the keys row:
Iterator keys = hashmap.keySet().iterator();
boolean notFirst = true;
while(keys.hasNext()) {
String key = (String)keys.next();
ArrayList tmp = (ArrayList)hashmap.get(key);
if(!notFirst) {
csv.append(",");
}
csv.append(key);
// store list
list.add(tmp);
notFirst = false;
}
csv.append("\n");
// Write the rest of the rows
while(row<numberOfTotalRow) {
notFirst = true;
for(int x=0;x<list.size();x++) {
if(!notFirst) {
csv.append(",");
}
csv.append((String)list.get(x).get(row));
notFirst = false;
}
row++;
}
回答2:
You can make a method that prints out the map as you wish:
public void toString(HashMap<String, ArrayList<String>> map) {
for(int i = 0; i < map.size(); i++) {
ArrayList<String> list = new ArrayList<String>(map.keySet());
String key = list.get(i);
System.out.println(key);
for(int j = 0; j < map.get(key).size(); j++)
System.out.println(map.get(key).get(j));
}
}
回答3:
The way you have imagined is impossible. A file is a continuous stream of bytes. So after you write the first value, you have this in your file : "value1\none\nthree\nfive". If you then seek to position 6 (after "value") and insert new characters, you'll be overwiting the first value's second row. The following bytes won't be magically pushed away.
The only way to do this is to traverse the data you have in a way that allows you to output the bytes in the same order that they will be in the file. So: go to each value and write the first element, to each value again and write their second element and so on.
回答4:
You don't need a RandomAccessFile
file, better use this:
HashMap<String, ArrayList<String>> map = new HashMap<>();
map.put("a", new ArrayList<>(Arrays.asList(new String[]{"A1", "A2", "A3"})));
map.put("b", new ArrayList<>(Arrays.asList(new String[]{"B1", "B2", "B3"})));
map.put("c", new ArrayList<>(Arrays.asList(new String[]{"C1", "C2", "C3"})));
{
/**
* Set your file printstream. For testing System.out
*/
PrintStream ps = System.out;
boolean first = true;
/**
* Size of the array list. Let's asume that the arraylist are of the
* same lenght;
*/
int s = 0;
/**
* Create a ArrayList variable because, this map class makes no guarantees
* as to the order of the map; in particular, it does not guarantee that
* the order will remain constant over time.
*/
ArrayList<Entry<String, ArrayList<String>>> l =
new ArrayList<>(map.entrySet());
for (Entry<String, ArrayList<String>> e : l) {
if (first) {
first = false;
s = e.getValue().size();
} else {
ps.print(",");
}
ps.print(e.getKey());
}
ps.println();
for (int i = 0; i < s; i++) {
first = true;
for (Entry<String, ArrayList<String>> e : l) {
if (first) {
first = false;
} else {
ps.print(",");
}
ps.print(
e.getValue().get(i));
}
ps.println();
}
}
Output:
b,c,a
B1,C1,A1
B2,C2,A2
B3,C3,A3
来源:https://stackoverflow.com/questions/11606376/write-data-from-hashmap-as-a-csv-file