假设我有一个散列图,其中String
类型为键,ArrayList
类型为值,示例{"value1"=["one","three","five"], "value2"=["two","four","six"]}
其中“value1”和“value2”为键。我想以下面的格式编写上面的hashmap数据。 (这样我就可以在excel中读取csv文件了)
value1,value2
one,two
three,four
five,six
我的想法是写下第一个键及其值如下
value1
one
three
five
然后我考虑使用RandomAccessFile
类中的seek方法返回第1行并再次写入第二个键及其值。但是我无法完成此任务,因为seek函数接受整个文件中的字符串长度并在其后写入新字符串。虽然我希望指针跳转到第一行并附加字符串。有一个更好的方法吗?。一个快速的例子将非常感激。
由于
答案 0 :(得分:1)
为什么你不能只使用4个字符串,每行一个?像这样:
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;
}
然后在最后,只需要4个字符串
String csv = keyRow.toString()+"\n"+value1.toString()+"\n"+value2.toString()+"\n"+value3.toString();
请注意,此示例并非正确的CSV。带逗号的字符串不包含在引号中。
如果你有数千行,你可以遍历HashMap一千次。为了节省一些查找密钥的时间,您可以将它们全部放在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++;
}
答案 1 :(得分:0)
您可以制作一个根据需要打印出地图的方法:
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));
}
}
答案 2 :(得分:0)
你想象的方式是不可能的。文件是连续的字节流。所以在你写完第一个值之后,你的文件就会出现这个:“value1 \ none \ nthree \ nfive”。如果您然后寻找位置6(在“值”之后)并插入新字符,您将覆盖第一个值的第二行。以下字节不会被神奇地推开。
执行此操作的唯一方法是以允许您按照文件中相同顺序输出字节的方式遍历您拥有的数据。所以:转到每个值并再次写入第一个元素,然后再写入第二个元素,依此类推。
答案 3 :(得分:0)
您不需要RandomAccessFile
文件,最好使用它:
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();
}
}
输出:
b,c,a
B1,C1,A1
B2,C2,A2
B3,C3,A3