Как разделить коллекцию на несколько других коллекций?

164
07 апреля 2022, 13:20

Допустим, у меня 5 полок для книг. Так же имеется коллекция (Collection<String>) с названиями книг. Каким образом я могу разделить эту коллекцию, чтобы на каждой полке было приблизительно равное количество книг? То есть разделить эту коллекцию на 5 частей. Может подскажете методы, примеры алгоритмов?

Answer 1

Можно еще сделать через Stream:

public static <T> Stream<Collection<T>> chunked(Stream<T> stream, int chunkSize) {
    AtomicInteger index = new AtomicInteger(0);
    return stream.collect(Collectors.groupingBy(x -> index.getAndIncrement() / chunkSize))
            .entrySet().stream().map(Map.Entry::getValue);
}

А дальше использовать так:

Collection<String> str = List.of("1", "2", "3", "4", "5");
Stream<Collection<String>> chunked = chunked(str.stream(), 2);
chunked.forEach(System.out::println);

Вывод:

[1, 2]
[3, 4]
[5]

Answer 2

Наверное, можно как-то так.

  1. Узнаём остаток от деления длины коллекции на кол-во коллекций, на которые надо оную разделить.
  2. Запускаем цикл, в котором режем коллекцию на новые коллекции, с длинной, равной кол-ву полок +1, где +1 добавляем столько раз, сколько у нас остаток в п.1 получился.
List<String> initialCollection = new ArrayList<String>();
for(int i = 0; i < 31; i++) {
    initialCollection.add("" + i);
}
List<List<String>> resultCollections = new ArrayList<>();
int remainder = initialCollection.size() % 5;
int minimumCollectionSize = initialCollection.size() / 5;
for (int i = 0; i < 5; i++) {
    int startIndex = i * minimumCollectionSize;
    int endIndex = (i + 1) * minimumCollectionSize;
    if (i < remainder) {
        startIndex += i;
        endIndex += i + 1;
    } else {
        startIndex += remainder;
        endIndex += remainder;
    }
    List<String> collectionPart = new ArrayList<>(initialCollection.subList(startIndex, endIndex));
    System.out.println(collectionPart.size() + "/ " + collectionPart);
    resultCollections.add(collectionPart);
}
System.out.println(resultCollections);

Проверить можно тут: https://ideone.com/u2UE4G

Answer 3

Можно пойти через нахождение остатка и использования ф-ции subList:

final int stairsCount = 3;
List<String> books = List.of("1", "2", "3", "4", "5", "6", "7", "8");
int residue = books.size() % stairsCount;
final int booksInEach = books.size() / stairsCount + (residue == 0 ? 0 : 1);
List<List<String>> stairsOfBooks = new ArrayList(stairsCount);
for(int i = 0; i < stairsCount - 1; i++){
    stairsOfBooks.add(books.subList(i * booksInEach, i * booksInEach + booksInEach));
}
if(stairsCount != 0){
    stairsOfBooks.add(books.subList((stairsCount - 1) * booksInEach, residue == 0 ? books.size() : (stairsCount - 1) * booksInEach + residue));
}

Убедиться в правильности можно поместив следующий код:

stairsOfBooks.get(stairsOfBooks.size() - 1).forEach(System.out::println);
System.out.println("---");

В концы блоков for и if.

Answer 4
public static void main (String[] args){
    int countBookOnShelf = 5; //кол-во книг на полке
    List<String> books =  Arrays.asList("book1", "book2", "book3", "book4", "book5", "book6"); //список книг
    List<List> shelfs = new ArrayList<>(); //полки
    List<String> shelf = new ArrayList<>(); //полка наполняемая в данный момент
    for(String book : books){
        shelf.add(book);
        //если кол-во книг на текущей полке превысило максимальное возможное кол-во книг на полке, то начинаем заполнять новую полку
        if(shelf.size() == countBookOnShelf ){
            shelfs.add(shelf);
            shelf = new ArrayList<>();
        }
    }
    if(shelf.size() > 0)  shelfs.add(shelf);
    System.out.println(shelfs);
}
READ ALSO
Intellij idea не работает. Не знаю в чем проблема

Intellij idea не работает. Не знаю в чем проблема

Я создал проект и после его сохранения и загрузки он перестал видеть директории и в том числе класс "main"

208
Метод toString()

Метод toString()

У меня вопрос про использование метода toString(), его переопределение На сколько я знаю, он используется для удобного вывода данных об объекте...

217
JavaFX зависает при поиске

JavaFX зависает при поиске

У меня в программе есть рекурсивный поиск и открытие файла, в обоих случаях программа зависает на время обработки, я пытался решить эту проблему,...

268