0Pricing
Kotlin Academy · Lekcja

Łańcuchy potoków i unikanie list pośrednich za pomocą Sequence

Buduj wieloetapowe potoki i używaj Sequence do leniwej ewaluacji.

Łańcuchy potoków i unikanie list pośrednich za pomocą Sequence to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Problem: listy pośrednie

Każda operacja na kolekcji (filter, map itd.) tworzy nową listę. W przypadku dużych kolekcji lub długich łańcuchów powoduje to niepotrzebne zużycie pamięci i czasu.

Ewaluacja zachłanna a leniwa

Operacje na kolekcjach są zachłanne: każdy krok w pełni przetwarza listę przed rozpoczęciem następnego. Operacje na sekwencjach są leniwe: każdy element przechodzi przez wszystkie kroki, zanim przetwarzanie przejdzie do kolejnego.

Konwersja na Sequence

Wywołanie asSequence() przełącza przetwarzanie z zachłannego (listowego) na leniwe (sekwencyjne).
val result = (1..1_000_000)
    .asSequence()
    .filter { it % 2 == 0 }
    .map { it * it }
    .take(5)
    .toList()
println(result)  // [4, 16, 36, 64, 100]

Sequence jest leniwa: brak działania przed operatorem terminalnym

Nie jest wykonywane żadne obliczenie, dopóki nie zostanie wywołany operator terminalny (toList, first, sum itd.).
val seq = generateSequence(1) { it + 1 }  // infinite!
    .filter { it % 3 == 0 }
    .map { it * it }
val first5 = seq.take(5).toList()
println(first5)  // [9, 36, 81, 144, 225]

generateSequence: nieskończone sekwencje

generateSequence tworzy leniwe, nieskończone sekwencje.
val fibonacci = generateSequence(Pair(0, 1)) { (a, b) -> Pair(b, a + b) }
    .map { it.first }
val first10 = fibonacci.take(10).toList()
println(first10)  // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Konstruktor sequence

Konstruktor sequence { } z yield tworzy niestandardowe leniwe sekwencje.
val evens = sequence {
    var n = 0
    while (true) {
        yield(n)
        n += 2
    }
}
println(evens.take(5).toList())  // [0, 2, 4, 6, 8]

Kiedy używać Sequence

Sequence należy używać, gdy kolekcja jest duża (>1000 elementów), używanych jest wiele połączonych operacji lub potrzebny jest tylko niewielki podzbiór wyników.

Kiedy NIE używać Sequence

W przypadku małych kolekcji (<100 elementów) sekwencje powodują dodatkowy narzut. Mechanizm oparty na iteratorze jest wolniejszy dla krótkich łańcuchów.
// Overkill for small list:
listOf(1, 2, 3).asSequence().map { it * 2 }.toList()
// Just use:
listOf(1, 2, 3).map { it * 2 }

Terminalne operacje Sequence

Operacje terminalne uruchamiają przetwarzanie. Typowe przykłady to: toList(), first(), last(), count(), sum(), any(), all(), none().
val s = (1..100).asSequence().filter { it % 7 == 0 }
println(s.first())          // 7
println(s.count())          // 14
println(s.sum())            // 728

Operacje stanowe a bezstanowe

Niektóre operacje na sekwencjach są stanowe (sort, distinct) — muszą zobaczyć wszystkie elementy, zanim wygenerują wynik. Przerywają one leniwą ewaluację.
val s = (1..10).asSequence()
    .filter { it > 3 }   // stateless: lazy
    .sorted()            // stateful: must see all elements
    .take(3).toList()
println(s)  // [4, 5, 6]

constrainOnce: bezpieczeństwo pojedynczej iteracji

Należy użyć constrainOnce(), aby sekwencja zgłaszała wyjątek przy próbie iteracji więcej niż jeden raz — jest to przydatne w przypadku strumieni.
val seq = generateSequence(1) { if (it < 5) it + 1 else null }
    .constrainOnce()
val first = seq.toList()   // OK
// val second = seq.toList()  // IllegalStateException!

Szybkie sprawdzenie

Kiedy Sequence rozpoczyna przetwarzanie elementów?

Podsumowanie

Sekwencje są leniwe — nie wykonują żadnej pracy przed operatorem terminalnym. Należy używać asSequence() dla dużych kolekcji z wieloma połączonymi operacjami. generateSequence i sequence { } tworzą nieskończone leniwe strumienie. Operacje terminalne uruchamiają przetwarzanie.

Często zadawane pytania

Czy lekcja „Łańcuchy potoków i unikanie list pośrednich za pomocą Sequence” jest bezpłatna?

Tak — pełny tekst „Łańcuchy potoków i unikanie list pośrednich za pomocą Sequence” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Łańcuchy potoków i unikanie list pośrednich za pomocą Sequence”?

Buduj wieloetapowe potoki i używaj Sequence do leniwej ewaluacji. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Łańcuchy potoków i unikanie list pośrednich za pomocą Sequence”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. map i flatMap: przekształcanie każdego elementu
  2. filter, filterNot i partition
  3. fold, reduce i runningFold
  4. Łańcuchy potoków i unikanie list pośrednich za pomocą Sequence
← Powrót do Kotlin Academy