如何在ArrayList中提取数据,直到RAM不会耗尽

时间:2016-12-16 10:33:25

标签: java arraylist

我正在编写一个java函数。此函数的返回类型为ArrayList<String> 可能存在这样的情况:返回的ArrayList具有接近大约100万个元素,并且它越过可用的RAM,并抛出异常。
我该如何处理这种情况。我不希望代码因例外而中断 有没有办法可以指定拉出特定数量的元素,然后丢弃它们并处理下几个元素......就像缓冲区大小一样?
以下是我正在做的代码:

ArrayList<String> users = getUsers(); 
...
...
...

private ArrayList<String> getUsers() throws Exception{
    //connect to MongoDB
    ArrayList<String> userList = new ArrayList<String>();
    userList = //get the list of users.
    return userList;
}

我想如果返回的列表超出可用内存限制,如果返回的列表太大,那么行ArrayList<String> users = getUsers();是否会抛出异常?
我该如何处理这种情况?

2 个答案:

答案 0 :(得分:2)

有两种标准解决方案可供考虑:

1)分页:将两个数字传递给指定页码和页面大小的方法。在调用代码中,在使用下一页编号再次调用方法之前处理结果:

private void processUsers() {
    int pageSize = 42;
    // the first page is page 1
    int page = 1;    
    List<String> users = getUsers(page, pageSize); 
    while(!users.isEmpty()) {        
        processPage(users);
        users = getPage(++page, pageSize); 
    }
}

private List<String> getPage(int page, int pageSize) {               
    int maxIndex = countTotalResults() - 1;
    int startIndex = Math.MIN((page - 1) * pageSize, maxIndex);
    int endIndex = Math.MIN(startIndex + pageSize, maxIndex);
    return listUsers(startIndex, endIndex);
}

2)流式传输:不返回List,而是返回Stream。使用Java 8流API处理流。甚至可以让JVM进程并行流,例如:

double average = roster
    .parallelStream()
    .filter(p -> p.getGender() == Person.Sex.MALE)
    .mapToInt(Person::getAge)
    .average()
    .getAsDouble();

https://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html

答案 1 :(得分:1)

您可以尝试使用以下内容对数据进行分页:

db.userdetails.find().skip(1000).limit(100);

在上面的场景中,您将跳过前10页并获取第11页。