ব্যাচগুলিতে তালিকা ভাঙ্গার জন্য কি কোনও সাধারণ জাভা ইউটিলিটি রয়েছে?


141

প্রদত্ত আকারের ব্যাচগুলিতে একটি তালিকা ভাঙার জন্য আমি নিজেই একটি ইউটিলিটি লিখেছি। আমি কেবল জানতে চেয়েছিলাম যে এর জন্য ইতিমধ্যে কোনও অ্যাপাচি কমন্স ব্যবহার করা আছে কিনা।

public static <T> List<List<T>> getBatches(List<T> collection,int batchSize){
    int i = 0;
    List<List<T>> batches = new ArrayList<List<T>>();
    while(i<collection.size()){
        int nextInc = Math.min(collection.size()-i,batchSize);
        List<T> batch = collection.subList(i,i+nextInc);
        batches.add(batch);
        i = i + nextInc;
    }

    return batches;
}

এর জন্য ইতিমধ্যে কোনও বিদ্যমান ইউটিলিটি রয়েছে কিনা তা আমাকে জানান।


4
নিশ্চিত নয় যে এটি অফ-টপিক। প্রশ্নটি "কোন লাইব্রেরি এটি করে" তা নয় তবে "আমি কীভাবে এপাচি সাধারণ ব্যবহারগুলি করতে পারি" is
ফ্লোরিয়ান এফ

@ ফ্লোরিয়ানএফ আমি আপনার সাথে একমত এই প্রশ্ন এবং এর উত্তরগুলি খুব দরকারী, এবং এটি একটি ছোট সম্পাদনার মাধ্যমে ভালভাবে সংরক্ষণ করা যেতে পারে। তাড়াতাড়ি বন্ধ করা এটি একটি অলস কর্ম ছিল action
এন্ডারি

: চমৎকার শ্রেণী এবং benchmarks এখানে পাওয়া দরকারী ব্লগ পোস্টে e.printstacktrace.blog/...
Benj

উত্তর:


250

গুগল পেয়ারা থেকে দেখুন : Lists.partition(java.util.List, int)

তালিকার একের পর এক সাবলিস্টিসম্য, একই আকারের প্রতিটি (চূড়ান্ত তালিকাটি ছোট হতে পারে) প্রদান করে। উদাহরণস্বরূপ, ধারণকারী একটি তালিকা পার্টিশন [a, b, c, d, e]3 উৎপাদনের একটি পার্টিশন আকার সঙ্গে [[a, b, c], [d, e]]একটি বাইরের তালিকা মূল অনুক্রমে তিন দুটি উপাদান দুটি ভেতরের তালিকা, সব ধারণকারী -।


লিঙ্ক partition documentation এবং লিঙ্ক code example
অস্টিন হাওস


3
f আপনি একটি তালিকা নিয়ে কাজ করছেন আমি "অ্যাপাচি কমন্স সংগ্রহ 4" লাইব্রেরিটি ব্যবহার করি। এটি তালিকার তালিকা বিভাগে একটি বিভাজন পদ্ধতি রয়েছে: ... int টার্গেটসাইজ = 100; তালিকা <Integer> largeList = ... তালিকা <তালিকা <Integer>> আউটপুট = তালিকাUtils.partition (বৃহত তালিকা, টার্গেটসাইজ); এই পদ্ধতিটি কোড. google.com/p/guava-libraries
স্বপ্নিল

1
ধন্যবাদ. জাভাতে এটি করা কতটা কঠিন তা আমি বিশ্বাস করতে পারি না।
চাচা লম্বা চুল

51

আপনি যদি জাভা -8 প্রবাহের ব্যাচ উত্পাদন করতে চান তবে আপনি নিম্নলিখিত কোডটি চেষ্টা করতে পারেন:

public static <T> Stream<List<T>> batches(List<T> source, int length) {
    if (length <= 0)
        throw new IllegalArgumentException("length = " + length);
    int size = source.size();
    if (size <= 0)
        return Stream.empty();
    int fullChunks = (size - 1) / length;
    return IntStream.range(0, fullChunks + 1).mapToObj(
        n -> source.subList(n * length, n == fullChunks ? size : (n + 1) * length));
}

public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

    System.out.println("By 3:");
    batches(list, 3).forEach(System.out::println);

    System.out.println("By 4:");
    batches(list, 4).forEach(System.out::println);
}

আউটপুট:

By 3:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10, 11, 12]
[13, 14]
By 4:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
[13, 14]

আমি কীভাবে ভাঙ্গি, চালিয়ে যাই বা এই পদ্ধতিতে ফিরে যাই?
মিরাল

15

আর একটি পদ্ধতি হ'ল Collectors.groupingByসূচকগুলি ব্যবহার করা এবং তারপরে প্রকৃত উপাদানগুলিতে শ্রেণিবদ্ধ সূচকগুলি ম্যাপ করা:

    final List<Integer> numbers = range(1, 12)
            .boxed()
            .collect(toList());
    System.out.println(numbers);

    final List<List<Integer>> groups = range(0, numbers.size())
            .boxed()
            .collect(groupingBy(index -> index / 4))
            .values()
            .stream()
            .map(indices -> indices
                    .stream()
                    .map(numbers::get)
                    .collect(toList()))
            .collect(toList());
    System.out.println(groups);

আউটপুট:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]


1
@ সিবিয়ান এটি সাধারণ ক্ষেত্রে কাজ করে। groupingByউপাদান সম্পন্ন হবে IntStream.rangeতালিকা উপাদান, না। উদাহরণস্বরূপ দেখুন ideone.com/KYBc7h
রেডিওডেফ

@ মোহাম্মদএল্রাশিডি সেবিয়ান তাদের মন্তব্য মুছে ফেলেছে, আপনি এখন আপনার মুছে ফেলতে পারেন।
অ্যালবার্ট হেন্ডরিক্স

7

আমি এই এক সাথে এসেছি:

private static <T> List<List<T>> partition(Collection<T> members, int maxSize)
{
    List<List<T>> res = new ArrayList<>();

    List<T> internal = new ArrayList<>();

    for (T member : members)
    {
        internal.add(member);

        if (internal.size() == maxSize)
        {
            res.add(internal);
            internal = new ArrayList<>();
        }
    }
    if (internal.isEmpty() == false)
    {
        res.add(internal);
    }
    return res;
}

6

জাভা 9 এর সাথে আপনি শর্ত IntStream.iterate()সহ ব্যবহার করতে পারেন hasNext। সুতরাং আপনি নিজের পদ্ধতির কোডটি এটিকে সহজ করতে পারেন:

public static <T> List<List<T>> getBatches(List<T> collection, int batchSize) {
    return IntStream.iterate(0, i -> i < collection.size(), i -> i + batchSize)
            .mapToObj(i -> collection.subList(i, Math.min(i + batchSize, collection.size())))
            .collect(Collectors.toList());
}

ব্যবহার করে {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, ফলাফলটি getBatches(numbers, 4)হবে:

[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]

5

নিম্নলিখিত উদাহরণটি একটি তালিকা কেড়ে নেওয়া দেখায়:

package de.thomasdarimont.labs;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SplitIntoChunks {

    public static void main(String[] args) {

        List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);

        List<List<Integer>> chunks = chunk(ints, 4);

        System.out.printf("Ints:   %s%n", ints);
        System.out.printf("Chunks: %s%n", chunks);
    }

    public static <T> List<List<T>> chunk(List<T> input, int chunkSize) {

        int inputSize = input.size();
        int chunkCount = (int) Math.ceil(inputSize / (double) chunkSize);

        Map<Integer, List<T>> map = new HashMap<>(chunkCount);
        List<List<T>> chunks = new ArrayList<>(chunkCount);

        for (int i = 0; i < inputSize; i++) {

            map.computeIfAbsent(i / chunkSize, (ignore) -> {

                List<T> chunk = new ArrayList<>();
                chunks.add(chunk);
                return chunk;

            }).add(input.get(i));
        }

        return chunks;
    }
}

আউটপুট:

Ints:   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Chunks: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]

4

এটির একটি সদৃশ বলে অন্য একটি প্রশ্ন ছিল যা এটি বন্ধ ছিল, তবে আপনি যদি এটি ঘনিষ্ঠভাবে পড়েন তবে তা সম্পূর্ণ আলাদা different সুতরাং যদি কেউ (আমার মতো) আসলে একটি তালিকাটিকে প্রায় সমান আকারের সাবলিস্টগুলির একটি নির্দিষ্ট সংখ্যায় বিভক্ত করতে চায় , তবে পড়ুন read

আমি এখানে জাভাতে বর্ণিত অ্যালগরিদমকে কেবল পোর্ট করেছি ।

@Test
public void shouldPartitionListIntoAlmostEquallySizedSublists() {

    List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g");
    int numberOfPartitions = 3;

    List<List<String>> split = IntStream.range(0, numberOfPartitions).boxed()
            .map(i -> list.subList(
                    partitionOffset(list.size(), numberOfPartitions, i),
                    partitionOffset(list.size(), numberOfPartitions, i + 1)))
            .collect(toList());

    assertThat(split, hasSize(numberOfPartitions));
    assertEquals(list.size(), split.stream().flatMap(Collection::stream).count());
    assertThat(split, hasItems(Arrays.asList("a", "b", "c"), Arrays.asList("d", "e"), Arrays.asList("f", "g")));
}

private static int partitionOffset(int length, int numberOfPartitions, int partitionIndex) {
    return partitionIndex * (length / numberOfPartitions) + Math.min(partitionIndex, length % numberOfPartitions);
}


3

ওয়েব থেকে বিভিন্ন চিট ব্যবহার করে, আমি এই সমাধানটিতে এসেছি:

int[] count = new int[1];
final int CHUNK_SIZE = 500;
Map<Integer, List<Long>> chunkedUsers = users.stream().collect( Collectors.groupingBy( 
    user -> {
        count[0]++;
        return Math.floorDiv( count[0], CHUNK_SIZE );
    } )
);

আমরা সাধারণ সংগ্রহ সূচকে নকল করতে গণনা ব্যবহার করি।
তারপরে, আমরা বালতি সংখ্যা হিসাবে বীজগণিত ভাগফল ব্যবহার করে বালতিগুলিতে সংগ্রহের উপাদানগুলিকে গ্রুপ করি।
চূড়ান্ত মানচিত্রে বালতি নম্বর হিসাবে কী হিসাবে বালতি নিজেই মান রয়েছে

তারপরে আপনি প্রতিটি বালতিতে সহজেই এর সাথে একটি অপারেশন করতে পারেন:

chunkedUsers.values().forEach( ... );

4
AtomicIntegerগণনার জন্য একটি ব্যবহার করতে পারে ।
jkschneider

1
List<T> batch = collection.subList(i,i+nextInc);
->
List<T> batch = collection.subList(i, i = i + nextInc);

1

স্ট্রিম এবং libs ছাড়া ওপি এর মতো, তবে সংক্ষিপ্ত:

public <T> List<List<T>> getBatches(List<T> collection, int batchSize) {
    List<List<T>> batches = new ArrayList<>();
    for (int i = 0; i < collection.size(); i += batchSize) {
        batches.add(collection.subList(i, Math.min(i + batchSize, collection.size())));
    }
    return batches;
}

0

এটি সমাধানের জন্য আরেকটি পদ্ধতি, প্রশ্ন:

public class CollectionUtils {

    /**
    * Splits the collection into lists with given batch size
    * @param collection to split in to batches
    * @param batchsize size of the batch
    * @param <T> it maintains the input type to output type
    * @return nested list
    */
    public static <T> List<List<T>> makeBatch(Collection<T> collection, int batchsize) {

        List<List<T>> totalArrayList = new ArrayList<>();
        List<T> tempItems = new ArrayList<>();

        Iterator<T> iterator = collection.iterator();

        for (int i = 0; i < collection.size(); i++) {
            tempItems.add(iterator.next());
            if ((i+1) % batchsize == 0) {
                totalArrayList.add(tempItems);
                tempItems = new ArrayList<>();
            }
        }

        if (tempItems.size() > 0) {
            totalArrayList.add(tempItems);
        }

        return totalArrayList;
    }

}

0

জাভা 8-এ একটি ওয়ান-লাইনারটি হ'ল:

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;

private static <T> Collection<List<T>> partition(List<T> xs, int size) {
    return IntStream.range(0, xs.size())
            .boxed()
            .collect(collectingAndThen(toMap(identity(), xs::get), Map::entrySet))
            .stream()
            .collect(groupingBy(x -> x.getKey() / size, mapping(Map.Entry::getValue, toList())))
            .values();

}

0

জাভা 8+ এর জন্য এখানে একটি সহজ সমাধান রয়েছে:

public static <T> Collection<List<T>> prepareChunks(List<T> inputList, int chunkSize) {
    AtomicInteger counter = new AtomicInteger();
    return inputList.stream().collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize)).values();
}

0

তালিকার ব্যাচটি পেতে আপনি নীচের কোডটি ব্যবহার করতে পারেন।

Iterable<List<T>> batchIds = Iterables.partition(list, batchSize);

উপরের কোডটি ব্যবহার করার জন্য আপনাকে গুগল পেয়ারা লাইব্রেরি আমদানি করতে হবে।


-1

import com.google.common.collect.Lists;

List<List<T>> batches = Lists.partition(List<T>,batchSize)

তালিকা.বিভাজন (তালিকা, ব্যাচসাইজ) ব্যবহার করুন। আপনাকে Listsগুগল সাধারণ প্যাকেজ ( com.google.common.collect.Lists) থেকে আমদানি করতে হবে

এটি এর List<T>সাথে তালিকার তালিকা এবং আপনার সমান প্রতিটি উপাদানের আকার প্রদান করবে batchSize


subList(startIndex, endIndex)প্রয়োজনীয় সূচকগুলির উপর ভিত্তি করে তালিক ভাঙার জন্য আপনি তাদের নিজস্ব পদ্ধতিও ব্যবহার করতে পারেন ।
v87278
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.