繁体   English   中英

如何在Java中有效处理数百万个元组的集合?

[英]How to efficiently handle a collection of millions of tuples in java?

我正在研究一个Java程序,该程序实际上是从Postgresql数据库中检索元组并对其进行一些处理。 我将每个元组表示为StringVector ,并将完整的元组(resultSet)表示为元组的向量。

Vector<String>         tuple;
Vector<Vector<String>> resultSet;

在我的应用程序中,我需要处理数百万个元组。 这是一个简单的基准测试,它通过简单地读取resultSet中的X个元组,然后打印resultSet Size(第一个和最后一个元组)来模拟我的程序。

基准测试考虑使用vector和arrayList表示元组

List<String>       tuple;
List<List<String>> resultSet;

基准程序代码

import java.util.Vector;
import java.util.List;
import java.util.ArrayList;

public class VectorVSarrayList {

  public static void loadDataInVector(Integer size){

    Vector<Vector<String>> r     = new Vector<Vector<String>>();
    Vector<String>         tuple = new Vector<String>();

    startTimer();  

    for(Integer i = 0; i < size; i++){

      tuple = new Vector<String>();

      for(int j = 0; j < 3; j ++)
        tuple.add(i.toString() + " tuple "+j);

      r.add(tuple);

    }

    endTimer("vector size " + r.size() + " first element : " + r.get(0).get(0) + ", and     last element : " + r.get(r.size()-1).get(0)); 

    r.clear();

  }

  public static void loadDataInArrayList(Integer size){

    List<List<String>> r     = new ArrayList<List<String>>();
    List<String>       tuple = new ArrayList<String>();


    startTimer();    

    for(Integer i = 0; i < size; i++){

      tuple = new ArrayList<String>();

      for(int j = 0; j < 3; j ++)
        tuple.add(i.toString() + " tuple "+j);

     r.add(tuple);
    }

    endTimer("array  size " + r.size() + " first element : " + r.get(0).get(0) + ", and  last element : " + r.get(r.size()-1).get(0)); 

    r.clear();       
  }

  public static void main(String [] args){

    Integer size = Integer.parseInt(args[0]);

    loadDataInArrayList(size);
    loadDataInVector(size);

    loadDataInArrayList(size);
    loadDataInVector(size);
  }

  private static long startTime = 0;
  private static long endTime   = 0;

  public static void startTimer(){
    startTime = System.currentTimeMillis();
  }

  public static void endTimer(String log){
        endTime = System.currentTimeMillis();
        System.out.println(log + ", " + (endTime - startTime) + ", ms");
 }


}

我已经运行基准测试来处理Java堆大小扩展到2G的1和1000万个元组,这是结果

> time java -Xmx2g VectorVSarrayList 1000000
array  size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 1642, ms
vector size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 1075, ms
array  size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 1625, ms
vector size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 308, ms

real    0m4.829s
user    0m14.849s
sys     0m0.500s


> time java -Xmx2g VectorVSarrayList 10000000
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at VectorVSarrayList.loadDataInArrayList(VectorVSarrayList.java:72)
    at VectorVSarrayList.main(VectorVSarrayList.java:28)

real    6m12.708s
user    22m57.662s
sys     0m6.200s

这些结果表明,即使只有1000万个元组,我也将花费至少6分钟的时间(相对于100万个元组的4秒),并最终运行OutOfMemory

OS         : Ubuntu 12.04
RAM        : 6 GB
processor  : Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz

有没有一种好的方法(更好的收藏方式或更好的实践方式)来进行这种类型的工作?

这取决于“一些工作”的意思,可以优化这个问题,我理解为分组从数据库中获取结果。

显然,您可以使用更有效的数据结构,而不会使堆溢出。 但是,每次数据更改(相关)时,都将需要维护。 在上述情况下,创建ArrayList的初始大小为3或更好地使用LinkedList。

另一种方法是让数据库已经准备好数据,以便这种准备支持您的操作。 喜欢

  • 按组键排序的数据排序(在数据库中)
  • 遍历数据,并在组键相同的情况下填充向量
  • 当组密钥更改对分组序列进行某些工作时(例如存储或打印出第一个,最后一个和大小或其他内容),并仅存储该序列的相关事实。
  • 完成数据后,对每个序列的结果进行处理,例如将其汇总

这种方法称为MapReduce,这里的映射(虚拟地)在数据库中完成,约简在程序中完成。

您可以尝试以下方法:

  1. 用每个String(或ArrayList字符串)的变量创建一个Tuple类
  2. 实现并重写hashCode()方法(例如,通过组合元组中每个String的每个hashCode的返回值)
  3. 创建一个HashMap [10] [10] hashMapArray = ...并使用两个嵌套的for循环在每个子数组中初始化HashMaps。
  4. 将每个元组放入hashMapArray中,并带有:

     int hash = Math.abs(Tuple.hashCode()); HashMap<Integer, Tuple> switchMap = hashMapArray [hash / 10][hash % 10]; switchMap.put(Tuple.hashCode(), Tuple); 

使用这种方法(或其变体)可能会大大提高程序速度。 我还必须实现一种快速排序和获取亿万个元素的方法,并且这种方法的持续时间从大约12分钟缩短到几秒钟。 并且请不要在将来使用Vector,它已被弃用为地狱:)

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM