Mam bardzo dużą kolekcję danych, a dane surowe są już posortowane według tego, co będzie kluczem. Na przykład mam plik CSV, a pierwsza kolumna będzie kluczem do grupowania.

A,x,x,x
A,x,y,x
A,z,y,y
C,x,s,d
C,t,d,s
B,a,s,a
E,x,x,x
E,t,r,y

Te linie są konwertowane na obiekty i umieścić na liście i przesyłane strumieniowo za pomocą RXJAVA Flowable. Ponieważ ten CSV będzie ogromny (tak ogromny, że spowoduje awarię aplikacji), czy istnieje dobry sposób na przekonwertowanie tych obiektów do wejścia na mapę, co wyglądałoby tak:

{ 'A': [[x,x,x],[x,y,x],[z,y,y]] }
4
Armin 22 luty 2019, 09:47

2 odpowiedzi

Najlepsza odpowiedź

Używam teraz FlowableTransformers.partialCollect. Przykład byłby przykład

Flowable.fromPublisher(FlowableTransformers.partialCollect(
        (Consumer<PartialCollectEmitter<LineData, Integer, 
        ListBuilder, ListDataModel>>) emitter -> {
            // Get or initialize collecting object
            ListBuilder lb = emitter.getAccumulator();
            if (lb == null) {
                lb = new ListBuilder();
                emitter.setAccumulator(lb);
            }

            if (emitter.demand() != 0) {
                boolean d = emitter.isComplete();
                if (emitter.size() != 0 && !d) {
                    LineData data = emitter.getItem(0);
                    emitter.dropItems(1);

                    // add returns the finished model if the prefix changes
                    ListDataModel model = lb.add(data);

                    if (model != null) {
                        emitter.next(model);
                    }
                } else if (d) {
                    if (!lb.isEmpty()) {
                        // clear returns the last model
                        emitter.next(lb.clear());
                    }
                    emitter.complete();
                    return;
                }
            }
            emitter.setIndex(0);
        }, Functions.emptyConsumer(), settings.getReadBufferSize() + 1).apply(
                Flowable.fromIterable(file.getFileNameList())
                        .concatMap(
                                fileName -> reader
                                        .getLineData(fileName)
                                        .buffer(settings.getReadBufferSize()))
                        .flatMap(Flowable::fromIterable)))
1
Community 27 luty 2019, 03:38

Użyj collectWhile z RXJava2-dodatki i określić fabrykę kolekcji, aby wytworzyć specjalny klucz obiekt:


class Keyed {
    final K key;
    final List<Value> list;
    ...
}

K key(Value value) {
 ...
}

source.compose(
  Transformers.
    collectWhile(
      // factory
      () -> new Keyed(),
      // add
      (keyed, x) -> { 
          keyed.list.add(x);
          return keyed; },
      // condition
      (keyed, x) -> 
         keyed.list.isEmpty() ||
         key(x).equals(keyed.key)));
0
Dave Moten 22 luty 2019, 23:08