Как стать автором
Обновить

Комментарии 19

Да, джаве прямо сильно не хватает extention-методов, можно было бы много острых углов стандартной библиотеки срезать.

Может и добавят их в будущих релизах Java. Ведь добавили же в 15 версии многострочные литералы)

Ммм, ну, типа, с подключением!

Спасибо)
Данный класс неизменяемый
— здесь вы могли использовать Records.
Да, вы правы. Однако record в Java 15 имеет статус preview и её нужно явно активировать. Мне же хотелось рассказать про ту функциональность обоих языков, которая доступна «из коробки».

В таких уроках надо упомянуть важный момент: методы наподобие map и filter на коллекциях создают новую коллекцию, то есть могут вести к серьёзному выделению памяти, даже если в конце вычислений используется один или всего несколько элементов. Для предотвращения этого надо брать последовательности (sequence) от коллекций: list.asSequence().map { ... }.filter { ...}, тогда вычисления могут быть ленивыми и без выделения памяти. Это аналог Stream в чистой Java.


Более того, если вам не нужны распараллеливаемые streams из Java, можно рекомендовать использовать только последовательности Kotlin — оверхед при выполнении может быть гораздо меньше. А ещё свои операторы для sequences написать гораздо легче, чем для streams.

Всё верно. Мне в статье хотелось прежде всего наглядно показать разницу в API двух языков. При этом если мы добавим к каждому примеру на kotlin использование asSequence(), то тем самым ещё и повысим производительность и уменьшим расход памяти.

Зато ленивые вычисления гораздо медленнее, поэтому говорить «надо брать последовательности (sequence) от коллекций» — некорректно. Надо определиться, что для данной задачи важнее: производительность, или минимизация накладных расходов, и выбирать жадный или ленивый вариант работы с коллекциями соответственно.

что-то как-то стримы сильно быстрее sequences

@Test
    fun testFib()
    {
        val fibonacciSequence = sequence {
            var a = 0
            var b = 1

            while (true) 
            {
                yield(a)
                val f = a + b
                a = b
                b = f
            }
        }

        val res = measureTimeMillis {
            fibonacciSequence
                    .take(10)
                    .groupBy { it % 2 == 0 }
                    .forEach(::println)
        }

    }

    @Test
    fun testFib1()
    {
        val fibonacciStream = Stream.iterate(Pair(1, 0)) { (a, b) ->
            Pair(b, a + b)
        }

        val res = measureTimeMillis {
            fibonacciStream
                    .limit(10)
                    .map { it.second }
                    .collect(Collectors.groupingBy { it % 2 == 0 })
                    .forEach(::println)
        }

    }


Или я что-то упустил?

Во-первых, так вы ничего не намеряете. Просто миллисекунды считать — это крайне грубо. Надо обязательно брать JMH.
Во-вторых, эта функция sequence работает через корутины. Да, там накладные расходы могуть быть побольше.
Более точным аналогом будет:


    generateSequence(1 to 0) { (a, b) -> b to a + b }
        .take(10)
        .map { it.second }
        .groupBy { it % 2 == 0 }
        .forEach(::println)

Здесь всё на обычных лямбдах и итераторах.

спасибо

у меня еще вопрос — если я делаю что-то типа myList.asSequence().flatMap{} и myList.stream().flatMap{}, последнее быстрее
Не подскажете, почему?
А можете полный пример привести? А то могут быть нюансы в зависимости от того, что вы в лямбдах указываете.
Очень весело наблюдать за тем, что называется новым и инновационным что в java, что в котлине, когда в groovy все это есть уже лет как 10))
Groovy допускает, например, динамическую типизацию, что делает его ближе к скриптовым языкам. А в больших проектах это может усложнять рефакторинг. С этой точки зрения можно сказать, что kotlin обладает преимуществами groovy (работа на JVM, совместимость с Java), но при этом лишён некоторых его минусов.
Можно ввести правило писать аннотацию CompileStatic и тогда отключается динамическая типизация.
оно то может быть и 10 лет в каком-то языке, но то что Kotlin намного интереснее, лаконичнее и понятнее той же Scala и Groovy.
Kotlin намного интереснее, лаконичнее и понятнее той же Scala

Как только Scala станет понятнее, а это обычно приходит с опытом, два остальных мифа мгновенно рассеются.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий