Java 8: GroupBy, подсчет и объединение - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь создать блок кода, который мне не совсем понятен. У меня есть список, скажем, 1000 строковых записей (по 3-10 символов в каждой), которые я собираю в одну строку, разделенную запятыми. Если общий размер символов в результирующей строке превышает 8100, мне нужно разделить список и создать две строки, разделенные запятыми (или 3, или любой другой фактор 8100). Я знаю, что для этого нужно groupingBy, но мой синтаксис не работает.

Итак, мой первый вопрос: как определить сумму символов в моем списке и как я могу сгруппировать список таким образом? что в каждой группе списков не более 8100 символов? Это то, что я до сих пор:

AtomicInteger counter = new AtomicInteger();
String codes = configInfos.stream()
    .map(ConfigInfo::getCode)
    .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / 8100))

Ответы [ 2 ]

4 голосов
/ 14 апреля 2020

Редактировать: не использовать потоки для этого

Мне нужно сохранить строку, когда я делю разделение. Он должен выглядеть как исходный список со списком 1 «Записи», «являются». Список 2 будет "три", "до". Список 3 будет "десять", "символы" и т. Д.

Потоковые операции не подходят для вашей задачи. Я рекомендую использовать классический l oop для самого понятного и простого в обслуживании кода.

Оригинальный ответ: Intstream.range ()

Не уверен, что это действительно то, что вам нужно. Если вы предпочитаете использовать поток, вот моя попытка:

    final int maxSubstringLength = 9; // 8100

    List<String> entries = List.of("Entries", "are", "three", "upto", "ten", "chars", "each");
    String totalString = entries.stream().collect(Collectors.joining(","));

    // round up in the division
    int substringCount = (totalString.length() + maxSubstringLength - 1) / maxSubstringLength;
    List<String> substrings = IntStream.range(0, substringCount)
            .mapToObj(i -> totalString.substring(i * maxSubstringLength, Math.min((i + 1) * maxSubstringLength, totalString.length())))
            .collect(Collectors.toList());

    substrings.forEach(System.out::println);

Вывод:

Entries,a
re,three,
upto,ten,
chars,eac
h

Для вашей очень длинной строки просто поставьте 8100 как максимальная длина подстроки, где я положил 9 для демонстрации.

4 голосов
/ 14 апреля 2020

Это нужно решить с помощью потоков?

В противном случае я бы решил это так:

String [] array = configInfos
    .stream()
    .map( ConfigInfo::getCode )
    .toArray( String []::new );
List<String> codes = new ArrayList<>();
StringJoiner joiner = new StringJoiner( "," );
for( String s : array )
{
    if( joiner.length() + 1 + s.length() > 8100 )
    {
        codes.add( joiner.toString() );
        joiner = new StringJoiner( "," );
    }
    joiner.add( s );
}
if( joiner.length() > 0 ) codes.add( joiner.toString() );

Но я должен признаться, я понятия не имею, как решить это с помощью потоков ...

...