it-swarm.com.de

Java 8-Partitionsliste

Ist es möglich, eine Liste in reinem Jdk8 in gleiche Abschnitte (Unterlisten) zu unterteilen.

Ich weiß, dass es mit Guava Lists class möglich ist, aber können wir das mit reinem Jdk machen? Ich möchte meinem Projekt keine neuen Gläser hinzufügen, sondern nur für einen Anwendungsfall.

LÖSUNGEN:

Die beste Lösung wurde bisher von tagir-valeev präsentiert:

Ich habe auch drei andere Möglichkeiten gefunden, aber sie sind nur für wenige Fälle gedacht:

1.Collectors.partitioningBy (), um die Liste in 2 Unterlisten aufzuteilen - wie folgt:

intList.stream().collect(Collectors.partitioningBy(s -> s > 6));
    List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());

2.Collectors.groupingBy (), um unsere Liste in mehrere Partitionen aufzuteilen:

 Map<Integer, List<Integer>> groups = 
      intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3));
    List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());

3.Aufteilung durch Trennzeichen:

List<Integer> intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8);

    int[] indexes = 
      Stream.of(IntStream.of(-1), IntStream.range(0, intList.size())
      .filter(i -> intList.get(i) == 0), IntStream.of(intList.size()))
      .flatMapToInt(s -> s).toArray();
    List<List<Integer>> subSets = 
      IntStream.range(0, indexes.length - 1)
               .mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1]))
               .collect(Collectors.toList());
15
Beri

Das geht ganz einfach mit der subList()-Methode:

List<String> collection = new ArrayList(21);
// fill collection
int chunkSize = 10;
List<List<String>> lists = new ArrayList<>();
for (int i=0; i<collection.size(); i+= chunkSize) {
    int end = Math.min(collection.size(), i + chunkSize);
    lists.add(collection.subList(i, end));
}
16
Robert

Versuchen Sie es mit diesem Code, es verwendet Java 8:

public static Collection<List<Integer>> splitListBySize(List<Integer> intList, int size) {

    if (!intList.isEmpty() && size > 0) {
        final AtomicInteger counter = new AtomicInteger(0);
        return intList.stream().collect(Collectors.groupingBy(it -> counter.getAndIncrement() / size)).values();
    }
    return null;
}
2
chabbi aissa

Ich habe meine eigene Lösung mit einem maßgeschneiderten Collector ausprobiert. Ich hoffe, jemand wird es nützlich finden oder mir helfen, es zu verbessern.

class PartitioningCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> {

        private final int batchSize;
        private final List<T> batch;

        public PartitioningCollector(int batchSize) {
            this.batchSize = batchSize;
            this.batch = new ArrayList<>(batchSize);
        }

        @Override
        public Supplier<List<List<T>>> supplier() {
            return LinkedList::new;
        }

        @Override
        public BiConsumer<List<List<T>>, T> accumulator() {
            return (total, element) -> {
                batch.add(element);
                if (batch.size() >= batchSize) {
                    total.add(new ArrayList<>(batch));
                    batch.clear();
                }
            };
        }

        @Override
        public BinaryOperator<List<List<T>>> combiner() {
            return (left, right) -> {
                List<List<T>> result = new ArrayList<>();
                result.addAll(left);
                result.addAll(left);
                return result;
            };
        }

        @Override
        public Function<List<List<T>>, List<List<T>>> finisher() {
            return result -> {
                if (!batch.isEmpty()) {
                    result.add(new ArrayList<>(batch));
                    batch.clear();
                }
                return result;
            };
        }

        @Override
        public Set<Characteristics> characteristics() {
            return emptySet();
        }
    }
0
Beri
private final String dataSheet = "103343262,6478342944, 103426540,84528784843, 103278808,263716791426, 103426733,27736529279, 
103426000,27718159078, 103218982,19855201547, 103427376,27717278645, 
103243034,81667273413";

    final int chunk = 2;
    AtomicInteger counter = new AtomicInteger();
    Collection<List<String>> chuncks= Arrays.stream(dataSheet.split(","))
            .map(String::trim)
            .collect(Collectors.groupingBy(i->counter.getAndIncrement()/chunk))
            .values();

ergebnis:

pairs =
 "103218982" -> "19855201547"
 "103278808" -> "263716791426"
 "103243034" -> "81667273413"
 "103426733" -> "27736529279"
 "103426540" -> "84528784843"
 "103427376" -> "27717278645"
 "103426000" -> "27718159078"
 "103343262" -> "6478342944"

Wir müssen jeweils 2 Elemente in Schlüssel-Wert-Paare gruppieren, damit die Liste in Teile von 2 aufgeteilt wird.

IntStream.range(0,6).forEach((i)->System.out.println(counter.getAndIncrement()/2));
prints:
0
0
1
1
2
2

Sie können die Blockgröße an die Größe der Partitionslisten anpassen.

0
Mohamed.Abdo