日期:2014-05-20  浏览次数:20845 次

高分!java 根据第一个文件内容从第二个文件读取
我有两个文件 一个叫id.txt
里面有很多行的数字
12
13
14
59
219
。。。
另一个叫list.txt
里面是这样的
12 [29,39,18,59]
13 [18.49,59,219]
14 [8,18,39]
59 [481]
..
希望输出的就是在list.txt里面 方括号中的信息在id.txt中也出现
比如id里面有59 那么12对应的输出应该是
12 [59]
13 [59,219]

我现在也写出来一个程序 但是速度非常慢 因为我的list.txt 大约有300M左右 而 id.txt也有10M 希望求高手帮我改进一下,或者重新写一个!在线等!

import java.io.*;
import java.util.*;
import java.lang.*;
public class trythis{ 
  public static void main(String args[])throws IOException
  File id = new File("id.txt");
  Scanner in = new Scanner(id);
  File friendship = new File("list.txt");
  Scanner inF= new Scanner(friendship);
   
  ArrayList<String> idArray = new ArrayList();
  //String [] userID;  
  //int size = 6;
  while (in.hasNextLine()){
  idArray.add(in.nextLine());  
  }
   
  String [] userFriend;
  Map<String, ArrayList> map_root = new HashMap<String, ArrayList>();
  while (inF.hasNextLine())
  {
  userFriend=inF.nextLine().split("\t");
  String friendList = userFriend[1].substring(userFriend[1].indexOf("[") + 1, userFriend[1].lastIndexOf("]"));
 
  String[] friends = friendList.split(",");
  ArrayList<String> als=new ArrayList();
  for(int i=0;i<friends.length;i++){
  als.add(friends[i]);
  }
  // System.out.println(als);
  map_root.put(userFriend[0],als);
   
  }
  // System.out.println(map_root);
  Map<String, ArrayList> map_rs = new HashMap<String, ArrayList>();
  for (String key : map_root.keySet()){
  ArrayList<String> resultList =new ArrayList(); 
  for (Iterator i = idArray.iterator(); i.hasNext();) { 
  Object temp = i.next(); 
  if (map_root.get(key).contains(temp)) { 
  resultList.add(temp.toString());
   
  } 
  map_rs.put(key, resultList);
  } 
  }  
  StringBuffer buf=new StringBuffer();
  for(String key:map_rs.keySet()){
  buf.append(key+" "+map_rs.get(key)+"\r\n");
  }
  FileOutputStream os=new FileOutputStream(new File("friends.txt"));
  os.write(buf.toString().getBytes(), 0, buf.toString().getBytes().length);  
  }
   
  }


------解决方案--------------------
几个关注点:
◎ 流式输入与流式输出,降低内存开销;
◎ 借助Hash提供快速检索,降低查找速度;
◎ 定期输出处理进度,避免盲目等待。


给点伪代码设计:
1、将id.txt中所有数字,读取入 HashSet ids 中
2、输出第一步的时间开销
3、准备一个复用的 StringBuilder sb
4、用 Scanner sc 打开 list.txt 文件
5、用 FileWriter fw 打开 friends.txt 文件
6、循环 sc.hasNextLine()
7、==拆解成字符数组friends(这里如果不拆解,直接按位处理性能更高);
8、==遍历字符数组->fid
9、----检查ids中是否存在该fid,存在则保存入sb
10、==检查sb长度是否>0
11、----将sb信息写入fw中
12、----将sb清空:sb.setLength(0)
13、==每1W笔处理,就输出一个时间
14、关闭fw,关闭sc

------解决方案--------------------
简单写了一个代码,有注释,楼主可以参考一下。
Java code
package net.csdn.bbs.mrsworf;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;

public class FindFriends {

    interface FriendFinder{
        void findFriends(File idFile, File listFile, File targetFile) throws IOException, IllegalAccessException;
    }
    
    static class EasyFriendFinder implements FriendFinder{
        private boolean ignoreWrongFormat = true;//是否忽略List文件中数据的格式错误
        private long wrongFormatCount = 0;//List文件中,数据格式错误的行数。
        public void findFriends(File idFile, File listFile, File targetFile) throws IOException, IllegalAccessException {
            // 由于ID文件大约10M,一般不会爆掉内存,所以,完全读取到内存中来
            HashSet<String> idCache = new HashSet<String>();
            BufferedReader reader = new BufferedReader(new FileReader(idFile));
            String line = null;
            try{
                while((line=reader.readLine())!=null){
                    if(line.trim().length()<=0)continue;
                    idCache.add(line.trim());
                }
            }finally{
                reader.close();
            }
            //读取List文件中的内容,同时,生成目标文件。
            reader = new BufferedReader(new FileReader(listFile));
            BufferedWriter writer = new BufferedWriter(new FileWriter(targetFile));
            try{
                while((line=reader.readLine())!=null){
                    //解析List文件中每一行的数据。 样例:12 [29,39,18,59]
                    int index = line.indexOf('[');//创建一个行级索引,辅助数据解析。
                    int index_ = line.lastIndexOf(']');//创建另一个行级索引,辅助数据解析。
                    if(index<0){
                        wrongFormatCount++;
                        if(ignoreWrongFormat)continue;//是否忽略List文件中数据的格式错误,如果不忽略则抛出异常,中断执行。
                        else throw new IllegalAccessException("数据格式不正确,没找到'['字符:"+line);
                    }
                    if(index_<0){
                        wrongFormatCount++;
                        if(ignoreWrongFormat)continue;//是否忽略List文件中数据的格式错误,如果不忽略则抛出异常,中断执行。
                        else throw new IllegalAccessException("数据格式不正确,没找到']'字符:"+line);
                    }
                    String id = line.substring(0,index).trim();
                    String allFriends = line.substring(index+1,index_);//所有的friend_id,以逗号分开。
                    String friends []  = allFriends.split("\\,|\\,");//以逗号为分隔符,拆分字符串
                    writer.write(id);writer.write(' ');writer.write('[');
                    for(int i=0;i<friends.length;i++){
                        if(idCache.contains(friends[i].trim())){
                            if(i>0)writer.write(',');
                            writer.write(friends[i]);
                        }
                    }
                    writer.write(']');writer.newLine();
                }
            }finally{
                writer.close();
                reader.close();//当writer.close()出现异常时,该语句将不会被执行,这是个BUG,楼主可以优化一下。
            }
        }
        public boolean isIgnoreWrongFormat() {
            return ignoreWrongFormat;
        }
        public void setIgnoreWrongFormat(boolean ignoreWrongFormat) {
            this.ignoreWrongFormat = ignoreWrongFormat;
        }
        public long getWrongFormatCount() {
            return wrongFormatCount;
        }
    }
    
    /**
     * 测试用例
     */
    public static void main(String[] args) {
        final String IdFile = "id.txt";
        final String ListFile = "list.txt";
        final String TargetFile = "friends.txt";
        
        FriendFinder finder = new EasyFriendFinder();
        try {
            finder.findFriends(new File(IdFile),new File(ListFile),new File(TargetFile));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }


}