Недостаточно памяти при создании фрагментов очень большого списка - PullRequest
0 голосов
/ 13 апреля 2020

Мне нужно получить список всех членов, возвращаемых публикуемым c API.

Проблема в том, что я не знаю никаких идентификаторов, но я знаю, что первый идентификатор начинается после 500000000, а последний один около 570000000. После проверки я знаю, что эти идентификаторы генерируются с отметкой времени, но у меня нет никакой другой информации.

Так что мое единственное решение - это получить их самостоятельно.

Я написал это:

private List<List<Long>> getFinalList() {
    return chunkArrayList(getInitList(), 100);
}

private List<Long> getInitList() {
    List<Long> idList = new ArrayList<>();
    for (long i = 500000000L; i < 570000000L; i++) {
        idList.add(i);
    }
    return idList;
}

private List<List<Long>> chunkArrayList(List<Long> listToChunk, int chunkSize) {
    AtomicInteger counter = new AtomicInteger();
    return new ArrayList<>(listToChunk.stream().collect(Collectors.groupingBy(l -> counter.getAndIncrement() / chunkSize)).values());
}

Примечание: я должен разделить свой список на более мелкие, чтобы разделить их на несколько вызовов API.

Моя главная проблема заключается в том, что этот код возвращает мне Out из памяти исключение, которое является нестабильным.

Как я могу сделать такой процесс, будучи максимально эффективным и избежать этих проблем с памятью?

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

Вы можете изменить типы возврата из списка в поток:

private Stream<List<Long>> getFinalList() {
    return chunkArrayList(getInitList(), 100);
}

private Stream<Long> getInitList() {        
    return LongStream.rangeClosed(500000000L, 570000000L).boxed();
}

public Stream<List<Long>> chunkArrayList(Stream<Long> stream, int chunkSize) {
    AtomicInteger counter = new AtomicInteger(0);
    return stream.collect(Collectors.groupingBy(x -> counter.getAndIncrement() / chunkSize))
            .values().stream();
}

, но, как уже упоминалось @Zag, нет необходимости делать это таким образом.

Что-то подобное может быть helpfull

public static void makeAnAPICallWithChunks(int chunkSize){
    LongStream.iterate(500000000L, x -> x + chunkSize)
              .boxed()
              .takeWhile(x -> x < 570000000L)
              .forEach(x -> {System.out.println(x + " to " + (x + chunkSize-1));});
}
2 голосов
/ 13 апреля 2020

Какой смысл составлять список из 7000000 предсказуемых значений? Если вы передаете chunked-списки в API, просто создайте эти меньшие списки по мере необходимости. Все, что вам нужно отслеживать, это какой номер использовать дальше.

...