Streams peek()?

0

Witam,
Jeżeli chcę wykonać na streamie jakąś metodę np. void intro() dokładnie raz, to peek(object->intro), czy isynieje lepsze rozwiązanie? Dzięki.

0

Co to znaczy tylko raz na streamie? Jak masz w strumieniu 10 elementów, to peek() wykona się 10 razy

0

Dzięki. A jak chcę wykonać cos raz? Mam taki stream np.:
fileContent.stream().skip(1)
.map(values -> mapper.buildObject(headers, values))
i chciałbym jakąś metodę wykonać na nim dokładnie raz?

0

To już jakiś zły design jest, ale możesz dać idą w peeku

0

Nie bardzo rozumiem co chcesz osiągnąć. Chcesz wywołać metodę tylko na 1 elemencie strumienia? o_O No mozesz zrobić tam peek, ale to jest jakiś mocno zrypany design.

0

Generalnie peek() jest do debugowania nie do przetwarzania danych.
Może tak, choć nie do końca rozumiem o co OPowi chodzi:

stream.limit(1).forEach(el -> el.foo());

Stream powinien być zakończony operacją terminalną peek() taką operacją nie jest więc może się nie wykonać.

Można też tak:

stream.findAny().ifPresent(el -> el.foo());
0
JajkoJajeczny napisał(a):

Dzięki. A jak chcę wykonać cos raz? Mam taki stream np.:
fileContent.stream().skip(1)
.map(values -> mapper.buildObject(headers, values))
i chciałbym jakąś metodę wykonać na nim dokładnie raz?

Zgaduje problem.
Czytasz z pliku CSV i w pierwszym wierszu masz headery które chcesz wczytać

Zgaduje rozwiązanie.
Pomysł pierwszy - prosty. Utwórz dwa streamy. Z pierwszego wczytaj tylko header, z drugiego resztę.
Pomysł drugi - szalony. Ponumeruj wszystkie elementy w streamie i wykonaj akcje w zależności od indeksu elementu.
Jak ponumerować elementy?
Po pierwsze potrzebujesz nieskończonego streamu liczb. coś w rodzaju IntStream.iterate(0, i -> i + 1);
Po drugie potrzebujesz metody zip i krotek - Streams .zip(indexStream, lineStream, (index, line) -> Pair.of(index,line)
Po trzecie potrzebujesz przekombinowanego mapowania - `map(pair -> pair.left() == 0 ? intro(pair.right()) : mapper.buildObject(headers,pair.right()))
Po czwarte to się nie uda bo się typy rozjadą, ale może po przeróbkach będzie Ci do czegoś przydatne :(

0

Duże dzięki. Fajni jesteście..

1
KamilAdam napisał(a):

Pomysł drugi - szalony. Ponumeruj wszystkie elementy w streamie i wykonaj akcje w zależności od indeksu elementu.

Pomysł trzeci, czyli jeszcze bardziej szalony - napisz własny Collector.

package csv;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

public class CsvCollector<T> implements Collector<String, CsvCollector.CsvData<T>, CsvCollector.CsvData<T>> {
    private final Function<String, T> mapper;
    private final String delimeter;
    private AtomicBoolean readHeaders = new AtomicBoolean(true);

    public CsvCollector(Function<String[], T> lineMapper, String delimeter) {
        Function<String, String[]> delimFunction = (s -> s.split(delimeter));

        this.delimeter = delimeter;
        this.mapper = delimFunction.andThen(lineMapper);
    }

    @Override
    public synchronized Supplier<CsvCollector.CsvData<T>> supplier() {
        return () -> new CsvData<>();
    }

    @Override
    public BiConsumer<CsvData<T>, String> accumulator() {
        return (csvData, line) -> {
            if (readHeaders.getAndSet(false)) {
                csvData.headers = line.split(delimeter);
            } else {
                csvData.data.add(mapper.apply(line));
            }
        };
    }

    @Override
    public BinaryOperator<CsvData<T>> combiner() {
        return ((csvData, csvData2) -> {
            csvData.data.addAll(csvData2.data);
            if (csvData2.headers != null) {
                csvData.headers = csvData2.headers;
            }

            return csvData;
        });
    }

    @Override
    public Function<CsvData<T>, CsvData<T>> finisher() {
        return Function.identity();
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
    }

    public static class CsvData<T> {
        private final List<T> data = new ArrayList<>();
        private String[] headers;

        public List<T> getData() {
            return data;
        }

        public String[] getHeaders() {
            return headers;
        }
    }
}
package csv;

import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Test {

    private final static String[] lines = {"First;Second", "1;2", "3;4"};

    public static void main(String[] args) {
        CsvCollector.CsvData<Integer[]> result = Stream.of(lines)
                .collect(new CsvCollector<>(Test::parseLine, ";"));

        System.out.println("Headers: " + Arrays.toString(result.getHeaders()));
        System.out.println("Lines:\n" + result.getData().stream().map(Arrays::toString).collect(Collectors.joining("\n")));
    }

    private static Integer[] parseLine(String[] line) {
        return Stream.of(line)
                .map(Integer::parseInt)
                .toArray(Integer[]::new);
    }
}

I nie, nie wiem czy bym się odważył zastosować to na produkcji :D

0

Mega. Dzięki Wartek...

1 użytkowników online, w tym zalogowanych: 0, gości: 1