解决方案 »

  1.   

    arraylist好像增删比较慢
    linkedlist比较适合频繁增删的
      

  2.   

    数据量巨大,是不是可以考虑异步读写?边读边写,一个共享的buffer
      

  3.   

    感谢回复,我这里好像没有频繁增删,主要是添加元素数量比较大。我研究下linkedlist试一下。
      

  4.   

    问题:
    1、大文件一次性读入会占用很多的内存,轻则拖慢应用,重则系统崩溃。
    2、读入内存,一次性保存在一个ArrayList中会进一步增加内存空间消耗。解决方法:
            大文件不要一次性读入内存,逐行处理,取一行处理一行。这样后面用到的ArrayList需要存储的值也自然少了。
            为了加快处理速度,可以使用多线程等方式并发处理,对刚接触Java的人来讲还略早。
      

  5.   

    感谢回复,我这里好像没有频繁增删,主要是添加元素数量比较大。我研究下linkedlist试一下。好像有个因素默认0.75,list生成时候有个默认大小,然后里面存到0.75比例就要扩容,不停存要不听扩,扩的过程会比linkedlist慢
    然后要边读边处理好像可以用ArrayBlockingQueue之类的,线程安全方便多线程
      

  6.   

    啊记错了...那个0.75是HashMap的...后面那部分扩容是对的应该,
    两种list实现的方法不一样
      

  7.   

      while (scanner.hasNext()){
                    double orix,oriy,dirx,diry;
                    int hitcount,raynum;
                    if (scanner.hasNextDouble()){
                        orix=scanner.nextDouble();oriy=scanner.nextDouble();
                        dirx=scanner.nextDouble();diry=scanner.nextDouble();
                        hitcount=(int)scanner.nextDouble();
                        raynum=(int)scanner.nextDouble();
                        ray newRay=new ray(orix,oriy,dirx,diry,hitcount);
                        newRay.setNo(raynum);
                        InputRays.add(newRay);
                    }
                    else {
                        String temp=scanner.next();
                    }
                }
    这样写有问题,因为你将创建的对象放入list中,垃圾回收机制是不能回收被list持有的对象,如果对象太多就会内存溢出。你可以一次创建5000个对象,将这些对象存入文件或者数据库中。这样就不会内存溢出了。
      

  8.   

    感谢回复。我爬网学习下你说的这个方法。随便写了个。没做测试,不确定有没有错。反正大致就是这么个思路
    用到了多线程、锁、匿名类、区块等等。本来还想用lambda表达式的,但是怕楼主jdk版本不够高……
    Ray[] buffer = new Ray[100];
    {
    for (int i=0;i<100;i++) {
    buffer[i] = new Ray();
    }
    }
    int readPointer = 0;
    int processPointer = 0;
    int size = 0;
    boolean eof = false;public void readRays(final String f) {
    new Thread() {
    public void run() {
    Scanner scanner = new Scanner(new FileInputStream(f)));
    while (scanner.hasNext()){
    synchronized(buffer) {
    if (size == 100) {
    buffer.wait();
    } else {
    ray[readPointer].orix = scanner.nextDouble();
    ray[readPointer].oriy = scanner.nextDouble();
    ray[readPointer].dirx = scanner.nextDouble();
    ray[readPointer].diry = scanner.nextDouble();
    ray[readPointer].hitcount = (int)scanner.nextDouble();
    ray[readPointer].raynum = (int)scanner.nextDouble();
    size++;
    readPointer = readPointer == 99 ? 0 : readPointer + 1;
    if (size == 1) {
    buffer.notifyAll();
    }
    }
    }
    }
    eof = true;
    }
    }.start();
    }public void processRays() {
    new Thread() {
    public void run() {
    while (!eof){
    synchronized(buffer) {
    if (size == 0) {
    buffer.wait();
    } else {
    processRay(ray[processPointer]);
    size--;
    processPointer = processPointer == 99 ? 0 : processPointer + 1;
    if (size == 99) {
    buffer.notifyAll();
    }
    }
    }
    }
    }
    }.start();
    }
      

  9.   

    等等……稍微想了下,感觉楼上的方法是错误的。直接锁整个buffer导致两个线程无法同时进行,效率反而比单线程更低。应该用 synchronized( buffer [pointer] ) (行级锁)
      

  10.   

    嗯,hashmap是为了防止hash碰撞,所以要留一部分空间。arraylist满了才扩容
    但是扩容主要影响的应该是cpu和内存读写速度,而不是内存容量。扩容后原本的数组会被垃圾回收的
      

  11.   

    不建议楼主一次性全部读取,  搜下java大型文件读取,有很多资料的
      

  12.   

    你的想法是对的。ArrayList本身底层的实现就决定了你处理的对象越多就会越慢,因为底层是固定长度的数组,你不停的加数据就涉及到数据扩容,扩容就涉及内存的拷贝,所以你看到的现象就是你的对象越多,扩容的速度就会越慢,最后就把你内存吃光。正确的处理思路就是适当的批量,比如你在ArrayList里一次性只装10000个,处理完了再装10000个
      

  13.   

    感谢回复。大文件的确应该边读边处理边释放资源,类似流式那样。多线程并发处理是高端了点,容我学习研究一番。收获关键词多线程并发处理,感谢。
    爬网查了下。arraylist扩容的确要慢点,我试试改成别的看看效率。感谢提供关键词ArrayBlockingQueue,我研究一下看看。
    感谢回复。这些对象后面还要用到,如果存到文件或者数据库,后面用的时候还是要加载到内存的吧。还是说也是边读边处理这样?或者你的意思是这样读取,垃圾回收机制就可以工作了?还请指导。
    非常感谢,还有例程,免了我爬网找例程之苦。多线程、匿名类、锁、区块我还没接触到,先学习研究一下。感谢提供关键词及例程。
    感谢回复。的确不能一次读取,后面我又试了一个GB级别的文件,直接内存不够了。
    感谢回复。批量处理看上去挺不错,可能没有边读边处理和多线程并发处理优雅高效,但对我这样技术小白应该是容易上手的,可以先从这里研究看看。
      

  14.   

    ArrayList底层是用数组来实现的,你不断往里加内容,导致数组不断变长。一开始数据量小数组拷贝还好,到后来数组变大,拷贝当然耗时
    解决方法就是一开始创建ArrayList时给足够的初始长度,这样后面就不用每次改变数组长度了
    List list = new ArrayList(100000) 
    希望能帮到你